blob: 785b8da698d12a8586dfd792bdf0387303378e6a [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:
Patrick Williamsedbf17d2024-12-18 11:22:04 -0500141 static constexpr struct pci_id_match match{
142 0x1050, 0x0750, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0};
Benjamin Faire5aafa52020-06-05 21:04:24 -0700143};
144
145class AspeedDevice : public Device
146{
147 public:
148 const struct pci_id_match* getMatch() const override
149 {
150 return &match;
151 }
152
153 struct pci_device getDevice() const override
154 {
155 struct pci_device dev;
156
157 dev.vendor_id = match.vendor_id;
158 dev.device_id = match.device_id;
159
160 dev.regions[1].is_IO = false;
161 dev.regions[1].base_addr = mockBaseAddr;
162 dev.regions[1].size = mockRegionSize;
163
164 return dev;
165 }
166
Willy Tu8a9de242020-10-30 11:00:21 -0700167 std::unique_ptr<PciBridgeIntf>
168 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const override
Benjamin Faire5aafa52020-06-05 21:04:24 -0700169 {
Willy Tu8a9de242020-10-30 11:00:21 -0700170 return std::make_unique<AspeedPciBridge>(pci, skipBridgeDisable);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700171 }
172
173 std::string getName() const override
174 {
175 return "Aspeed"s;
176 }
177
178 /* Offset to the config region */
179 static constexpr int config = 0x0f000;
180 /* Lower bit determines whether bridge is enabled */
181 static constexpr std::uint8_t bridgeEnabled = 0x01;
182 /* Offset to the MMIO address configuration */
183 static constexpr int bridge = 0x0f004;
184
185 private:
Patrick Williamsedbf17d2024-12-18 11:22:04 -0500186 static constexpr struct pci_id_match match{
187 0x1a03, 0x2000, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0};
Benjamin Faire5aafa52020-06-05 21:04:24 -0700188};
189
190NuvotonDevice nuvotonDevice;
191AspeedDevice aspeedDevice;
192
193class PciSetupTest : public testing::TestWithParam<Device*>
194{};
195
196/* Handle device not found */
197TEST_P(PciSetupTest, NotFound)
Benjamin Fair20a18092020-06-08 11:12:21 -0700198{
199 PciAccessMock pciMock;
200
Benjamin Faire5aafa52020-06-05 21:04:24 -0700201 InSequence in;
202
203 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
204 PciIdMatch(GetParam()->getMatch())))
205 .WillOnce(Return(mockIter));
206 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
207 .WillOnce(Return(nullptr));
208 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
209
210 EXPECT_THROW(GetParam()->getBridge(&pciMock), NotFoundException);
211}
212
213/* Test finding device but probe fails */
214TEST_P(PciSetupTest, ProbeFail)
215{
216 PciAccessMock pciMock;
217 struct pci_device dev;
218
219 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
220 PciIdMatch(GetParam()->getMatch())))
221 .WillOnce(Return(mockIter));
222 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
223 .WillOnce(Return(&dev))
224 .WillRepeatedly(Return(nullptr));
225
226 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev))).WillOnce(Return(EFAULT));
227
228 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
229
230 EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
231}
232
233/* Test finding device but mapping fails */
234TEST_P(PciSetupTest, MapFail)
235{
236 PciAccessMock pciMock;
237 struct pci_device dev;
238
239 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
240 PciIdMatch(GetParam()->getMatch())))
241 .WillOnce(Return(mockIter));
242 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
243 .WillOnce(Return(&dev))
244 .WillRepeatedly(Return(nullptr));
245
246 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
247 .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
248
249 EXPECT_CALL(pciMock,
250 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
251 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
252 .WillOnce(Return(EFAULT));
253
254 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
255
256 EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
257}
258
259/* Test finding device but unmapping fails */
260TEST_P(PciSetupTest, UnmapFail)
261{
262 PciAccessMock pciMock;
263 struct pci_device dev;
264 std::vector<std::uint8_t> region(mockRegionSize);
265
266 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
267 PciIdMatch(GetParam()->getMatch())))
268 .WillOnce(Return(mockIter));
269 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
270 .WillOnce(Return(&dev))
271 .WillRepeatedly(Return(nullptr));
272
273 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
274 .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
275
276 EXPECT_CALL(pciMock,
277 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
278 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
279 .WillOnce(DoAll(SetArgPointee<4>(region.data()), Return(0)));
280
281 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
282 EXPECT_CALL(pciMock, pci_device_unmap_range(Eq(&dev), Eq(region.data()),
283 mockRegionSize))
284 .WillOnce(Return(EFAULT));
285
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700286 GetParam()->expectSetup(pciMock, dev);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700287 // This will print an error but not throw
288 GetParam()->getBridge(&pciMock);
289}
290
291/* Create expectations on pciMock for finding device and mapping memory region
292 */
293void expectSetup(PciAccessMock& pciMock, struct pci_device& dev, Device* param,
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700294 std::uint8_t* region, bool deviceExpectations = true)
Benjamin Faire5aafa52020-06-05 21:04:24 -0700295{
296 EXPECT_CALL(pciMock,
297 pci_id_match_iterator_create(PciIdMatch(param->getMatch())))
298 .WillOnce(Return(mockIter));
299 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
300 .WillOnce(Return(&dev))
301 .WillRepeatedly(Return(nullptr));
302
303 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
304 .WillOnce(DoAll(Assign(&dev, param->getDevice()), Return(0)));
305
306 EXPECT_CALL(pciMock,
307 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
308 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
309 .WillOnce(DoAll(SetArgPointee<4>(region), Return(0)));
310
311 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
312 EXPECT_CALL(pciMock,
313 pci_device_unmap_range(Eq(&dev), Eq(region), mockRegionSize))
314 .WillOnce(Return(0));
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700315
Vivekanand Veeracholan55b1a712021-02-18 12:06:37 -0800316 EXPECT_CALL(pciMock, pci_device_enable(Eq(&dev))).Times(1);
317
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700318 if (deviceExpectations)
319 param->expectSetup(pciMock, dev);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700320}
321
322/* Test finding device and mapping memory region */
323TEST_P(PciSetupTest, Success)
324{
325 PciAccessMock pciMock;
326 struct pci_device dev;
327 std::vector<std::uint8_t> region(mockRegionSize);
328
329 expectSetup(pciMock, dev, GetParam(), region.data());
330
331 GetParam()->getBridge(&pciMock);
332}
333
334INSTANTIATE_TEST_SUITE_P(Default, PciSetupTest,
335 ::testing::Values(&nuvotonDevice, &aspeedDevice),
336 [](const testing::TestParamInfo<Device*>& info) {
Patrick Williams42a44c22024-08-16 15:21:32 -0400337 return info.param->getName();
338 });
Benjamin Faire5aafa52020-06-05 21:04:24 -0700339
340TEST(NuvotonWriteTest, TooLarge)
341{
342 PciAccessMock pciMock;
343 struct pci_device dev;
344 std::vector<std::uint8_t> region(mockRegionSize);
345 std::vector<std::uint8_t> data(0x4001);
346
347 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
348
349 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
Patrick Williams28c00d62022-04-27 08:37:13 -0500350 EXPECT_THROW(bridge->write(std::span<std::uint8_t>(data)), ToolException);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700351}
352
353TEST(NuvotonWriteTest, Success)
354{
355 PciAccessMock pciMock;
356 struct pci_device dev;
357 std::vector<std::uint8_t> region(mockRegionSize);
358 std::vector<std::uint8_t> data(0x4000);
359
360 std::generate(data.begin(), data.end(), std::rand);
361
362 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
363
364 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
Patrick Williams28c00d62022-04-27 08:37:13 -0500365 bridge->write(std::span<std::uint8_t>(data));
Benjamin Faire5aafa52020-06-05 21:04:24 -0700366
Patrick Williams28c00d62022-04-27 08:37:13 -0500367 EXPECT_THAT(std::span<uint8_t>(&region[0], data.size()),
368 SpanEq(std::span<uint8_t>(data)));
Benjamin Faire5aafa52020-06-05 21:04:24 -0700369}
370
371TEST(NuvotonConfigureTest, Success)
372{
373 PciAccessMock pciMock;
374 struct pci_device dev;
375 std::vector<std::uint8_t> region(mockRegionSize);
376 ipmi_flash::PciConfigResponse config{0x123bea51};
377
378 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
379
380 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
381 bridge->configure(config);
382
383 /* No effect from calling configure(), so the whole region should be 0 */
384 EXPECT_THAT(region, Each(0));
385}
386
387TEST(NuvotonDataLengthTest, Success)
388{
389 PciAccessMock pciMock;
390 struct pci_device dev;
391 std::vector<std::uint8_t> region(mockRegionSize);
392
393 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
394
395 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
396 EXPECT_EQ(bridge->getDataLength(), 0x4000);
397}
398
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700399/* Make sure config register is left alone if the bridge is already enabled */
400TEST(NuvotonBridgeTest, AlreadyEnabledSuccess)
401{
402 PciAccessMock pciMock;
403 struct pci_device dev;
404 std::vector<std::uint8_t> region(mockRegionSize);
405
406 constexpr std::uint8_t defaultVal = 0x40;
407
408 /* Only set standard expectations; not those from nuvotonDevice */
409 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
410
411 {
412 InSequence in;
413
414 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
415 NuvotonDevice::config))
416 .WillOnce(DoAll(
417 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
418 Return(0)));
419
420 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
421 NuvotonDevice::config))
422 .WillOnce(DoAll(
423 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
424 Return(0)));
425 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal,
426 NuvotonDevice::config))
427 .WillOnce(Return(0));
428 }
429
430 nuvotonDevice.getBridge(&pciMock);
431}
432
433/* Read fails when attempting to setup the bridge */
434TEST(NuvotonBridgeTest, ReadSetupFail)
435{
436 PciAccessMock pciMock;
437 struct pci_device dev;
438 std::vector<std::uint8_t> region(mockRegionSize);
439
440 /* Only set standard expectations; not those from nuvotonDevice */
441 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
442
443 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
444 NuvotonDevice::config))
445 .WillOnce(Return(EFAULT));
446
447 EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error);
448}
449
450/* Write fails when attempting to setup the bridge */
451TEST(NuvotonBridgeTest, WriteSetupFail)
452{
453 PciAccessMock pciMock;
454 struct pci_device dev;
455 std::vector<std::uint8_t> region(mockRegionSize);
456
457 constexpr std::uint8_t defaultVal = 0x40;
458
459 /* Only set standard expectations; not those from nuvotonDevice */
460 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
461
462 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
463 NuvotonDevice::config))
464 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
465 EXPECT_CALL(pciMock,
466 pci_device_cfg_write_u8(
467 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
468 NuvotonDevice::config))
469 .WillOnce(Return(EFAULT));
470
471 EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error);
472}
473
474/* Read fails when attempting to disable the bridge */
475TEST(NuvotonBridgeTest, ReadDisableFail)
476{
477 PciAccessMock pciMock;
478 struct pci_device dev;
479 std::vector<std::uint8_t> region(mockRegionSize);
480
481 constexpr std::uint8_t defaultVal = 0x40;
482
483 /* Only set standard expectations; not those from nuvotonDevice */
484 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
485
486 {
487 InSequence in;
488
489 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
490 NuvotonDevice::config))
491 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
492 EXPECT_CALL(pciMock,
493 pci_device_cfg_write_u8(
494 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
495 NuvotonDevice::config))
496 .WillOnce(Return(0));
497
498 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
499 NuvotonDevice::config))
500 .WillOnce(Return(EFAULT));
501 }
502
503 nuvotonDevice.getBridge(&pciMock);
504}
505
506/* Write fails when attempting to disable the bridge */
507TEST(NuvotonBridgeTest, WriteDisableFail)
508{
509 PciAccessMock pciMock;
510 struct pci_device dev;
511 std::vector<std::uint8_t> region(mockRegionSize);
512
513 constexpr std::uint8_t defaultVal = 0x40;
514
515 /* Only set standard expectations; not those from nuvotonDevice */
516 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
517
518 {
519 InSequence in;
520
521 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
522 NuvotonDevice::config))
523 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
524 EXPECT_CALL(pciMock,
525 pci_device_cfg_write_u8(
526 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
527 NuvotonDevice::config))
528 .WillOnce(Return(0));
529
530 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
531 NuvotonDevice::config))
532 .WillOnce(DoAll(
533 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
534 Return(0)));
535 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal,
536 NuvotonDevice::config))
537 .WillOnce(Return(EFAULT));
538 }
539
540 nuvotonDevice.getBridge(&pciMock);
541}
542
543/* Make sure the bridge gets enabled when needed */
544TEST(NuvotonBridgeTest, NotEnabledSuccess)
545{
546 PciAccessMock pciMock;
547 struct pci_device dev;
548 std::vector<std::uint8_t> region(mockRegionSize);
549
550 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
551 nuvotonDevice.getBridge(&pciMock);
552}
553
Willy Tu8a9de242020-10-30 11:00:21 -0700554/* Make sure it skips the disable bridge call when skipBridgeDisable is true */
555TEST(NuvotonBridgeTest, SkipDisable)
556{
557 PciAccessMock pciMock;
558 struct pci_device dev;
559 std::vector<std::uint8_t> region(mockRegionSize);
560
561 constexpr std::uint8_t defaultVal = 0x40;
562
563 /* Only set standard expectations; not those from nuvotonDevice */
564 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
565
566 {
567 InSequence in;
568
569 /* Only expect call for enableBridge() */
570 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
571 NuvotonDevice::config))
572 .WillOnce(DoAll(
573 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
574 Return(0)));
575 }
576
577 /* Setting skipBridgeDisable to true */
578 nuvotonDevice.getBridge(&pciMock, true);
579}
580
Benjamin Faire5aafa52020-06-05 21:04:24 -0700581TEST(AspeedWriteTest, TooLarge)
582{
583 PciAccessMock pciMock;
584 struct pci_device dev;
585 std::vector<std::uint8_t> region(mockRegionSize);
586 std::vector<std::uint8_t> data(0x10001);
587
588 expectSetup(pciMock, dev, &aspeedDevice, region.data());
589
590 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
Patrick Williams28c00d62022-04-27 08:37:13 -0500591 EXPECT_THROW(bridge->write(std::span<std::uint8_t>(data)), ToolException);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700592}
593
594TEST(AspeedWriteTest, Success)
595{
596 PciAccessMock pciMock;
597 struct pci_device dev;
598 std::vector<std::uint8_t> region(mockRegionSize);
599 std::vector<std::uint8_t> data(0x10000);
600
601 std::generate(data.begin(), data.end(), std::rand);
602
603 expectSetup(pciMock, dev, &aspeedDevice, region.data());
604
605 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
Patrick Williams28c00d62022-04-27 08:37:13 -0500606 bridge->write(std::span<std::uint8_t>(data));
Benjamin Faire5aafa52020-06-05 21:04:24 -0700607
Patrick Williams28c00d62022-04-27 08:37:13 -0500608 EXPECT_THAT(std::span<uint8_t>(&region[0x10000], data.size()),
609 SpanEq(std::span<uint8_t>(data)));
Benjamin Faire5aafa52020-06-05 21:04:24 -0700610}
611
612TEST(AspeedConfigureTest, Success)
613{
614 PciAccessMock pciMock;
615 struct pci_device dev;
616 std::vector<std::uint8_t> region(mockRegionSize);
617 ipmi_flash::PciConfigResponse config{0x123bea51};
618
619 expectSetup(pciMock, dev, &aspeedDevice, region.data());
620
621 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
622 bridge->configure(config);
623
624 auto configSpan = stdplus::raw::asSpan<uint8_t>(config);
625 EXPECT_THAT(
Patrick Williams28c00d62022-04-27 08:37:13 -0500626 std::span<uint8_t>(&region[AspeedDevice::bridge], sizeof(config)),
Benjamin Faire5aafa52020-06-05 21:04:24 -0700627 SpanEq(configSpan));
628}
629
630TEST(AspeedDataLengthTest, Success)
631{
632 PciAccessMock pciMock;
633 struct pci_device dev;
634 std::vector<std::uint8_t> region(mockRegionSize);
635
636 expectSetup(pciMock, dev, &aspeedDevice, region.data());
637
638 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
639 EXPECT_EQ(bridge->getDataLength(), 0x10000);
640}
641
642/* Make sure config region is left alone if the bridge is already enabled */
643TEST(AspeedBridgeTest, AlreadyEnabledSuccess)
644{
645 PciAccessMock pciMock;
646 struct pci_device dev;
647 std::vector<std::uint8_t> region(mockRegionSize);
648
649 constexpr std::uint8_t defaultVal = 0x42;
650
651 region[AspeedDevice::config] = defaultVal | AspeedDevice::bridgeEnabled;
652
653 expectSetup(pciMock, dev, &aspeedDevice, region.data());
654
655 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
656
657 {
658 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
Patrick Williams42a44c22024-08-16 15:21:32 -0400659 enabledRegion[AspeedDevice::config] =
660 defaultVal | AspeedDevice::bridgeEnabled;
Benjamin Faire5aafa52020-06-05 21:04:24 -0700661 EXPECT_THAT(region, ContainerEq(enabledRegion));
662 }
663
664 bridge.reset();
665
666 {
667 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
668 disabledRegion[AspeedDevice::config] = defaultVal;
669 EXPECT_THAT(region, ContainerEq(disabledRegion));
670 }
671}
672
Willy Tu8a9de242020-10-30 11:00:21 -0700673/* Make sure the config region remains the same even after cleanup if
674 * skipBridgeDisable is true */
675TEST(AspeedBridgeTest, SkipDisable)
676{
677 PciAccessMock pciMock;
678 struct pci_device dev;
679 std::vector<std::uint8_t> region(mockRegionSize);
680
681 constexpr std::uint8_t defaultVal = 0x42;
682
683 region[AspeedDevice::config] = defaultVal | AspeedDevice::bridgeEnabled;
684
685 expectSetup(pciMock, dev, &aspeedDevice, region.data());
686
687 /* Setting skipBridgeDisable to true */
Patrick Williams42a44c22024-08-16 15:21:32 -0400688 std::unique_ptr<PciBridgeIntf> bridge =
689 aspeedDevice.getBridge(&pciMock, true);
Willy Tu8a9de242020-10-30 11:00:21 -0700690
691 {
692 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
Patrick Williams42a44c22024-08-16 15:21:32 -0400693 enabledRegion[AspeedDevice::config] =
694 defaultVal | AspeedDevice::bridgeEnabled;
Willy Tu8a9de242020-10-30 11:00:21 -0700695 EXPECT_THAT(region, ContainerEq(enabledRegion));
696 }
697
698 bridge.reset();
699
700 {
701 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
Patrick Williams42a44c22024-08-16 15:21:32 -0400702 disabledRegion[AspeedDevice::config] =
703 defaultVal | AspeedDevice::bridgeEnabled;
Willy Tu8a9de242020-10-30 11:00:21 -0700704 EXPECT_THAT(region, ContainerEq(disabledRegion));
705 }
706}
707
Benjamin Faire5aafa52020-06-05 21:04:24 -0700708/* Make sure the bridge gets enabled when needed */
709TEST(AspeedBridgeTest, NotEnabledSuccess)
710{
711 PciAccessMock pciMock;
712 struct pci_device dev;
713 std::vector<std::uint8_t> region(mockRegionSize);
714
715 constexpr std::uint8_t defaultVal = 0x42;
716
717 region[AspeedDevice::config] = defaultVal;
718
719 expectSetup(pciMock, dev, &aspeedDevice, region.data());
720
721 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
722
723 {
724 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
Patrick Williams42a44c22024-08-16 15:21:32 -0400725 enabledRegion[AspeedDevice::config] =
726 defaultVal | AspeedDevice::bridgeEnabled;
Benjamin Faire5aafa52020-06-05 21:04:24 -0700727 EXPECT_THAT(region, ContainerEq(enabledRegion));
728 }
729
730 bridge.reset();
731
732 {
733 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
734 disabledRegion[AspeedDevice::config] = defaultVal;
735 EXPECT_THAT(region, ContainerEq(disabledRegion));
736 }
Benjamin Fair20a18092020-06-08 11:12:21 -0700737}
738
739} // namespace
740} // namespace host_tool