blob: ca6b7abc9204296eb9720d08bdf1c70c50250c3f [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>
26#include <string>
27#include <vector>
Benjamin Fair20a18092020-06-08 11:12:21 -070028
29#include <gtest/gtest.h>
30
31namespace host_tool
32{
33namespace
34{
35
Benjamin Faire5aafa52020-06-05 21:04:24 -070036using namespace std::string_literals;
37
38using ::testing::Assign;
39using ::testing::ContainerEq;
40using ::testing::DoAll;
41using ::testing::Each;
42using ::testing::Eq;
43using ::testing::InSequence;
44using ::testing::NotNull;
45using ::testing::Return;
46using ::testing::SetArgPointee;
47
48// TODO: switch to ConainerEq for C++20
49MATCHER_P(SpanEq, s, "")
50{
51 return arg.size() == s.size() && !memcmp(arg.data(), s.data(), s.size());
52}
53
54MATCHER_P(PciIdMatch, m, "")
55{
56 return (arg->vendor_id == m->vendor_id && arg->device_id == m->device_id &&
57 arg->subvendor_id == m->subvendor_id &&
58 arg->subdevice_id == m->subdevice_id);
59}
60
61pci_device_iterator* mockIter = reinterpret_cast<pci_device_iterator*>(0x42);
62
63constexpr pciaddr_t mockBaseAddr = 0xdeadbeef;
64constexpr pciaddr_t mockRegionSize = 0x20000;
65
66class Device
67{
68 public:
Patrick Venturee261ca22020-09-28 12:47:39 -070069 virtual ~Device() = default;
Benjamin Faire5aafa52020-06-05 21:04:24 -070070 virtual const struct pci_id_match* getMatch() const = 0;
71 virtual struct pci_device getDevice() const = 0;
Willy Tub487eb42021-09-16 21:44:43 -070072 virtual void expectSetup(PciAccessMock&, const struct pci_device&) const {};
Willy Tu8a9de242020-10-30 11:00:21 -070073 virtual std::unique_ptr<PciBridgeIntf>
74 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const = 0;
Benjamin Faire5aafa52020-06-05 21:04:24 -070075 virtual std::string getName() const = 0;
76};
77
78class NuvotonDevice : public Device
79{
80 public:
81 const struct pci_id_match* getMatch() const override
82 {
83 return &match;
84 }
85
86 struct pci_device getDevice() const override
87 {
88 struct pci_device dev;
89
90 dev.vendor_id = match.vendor_id;
91 dev.device_id = match.device_id;
92
93 dev.regions[0].is_IO = false;
94 dev.regions[0].base_addr = mockBaseAddr;
95 dev.regions[0].size = mockRegionSize;
96
97 return dev;
98 }
99
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700100 void expectSetup(PciAccessMock& pciMock,
101 const struct pci_device& dev) const override
102 {
103 static constexpr std::uint8_t defaultVal = 0x40;
104
105 InSequence in;
106
107 EXPECT_CALL(pciMock,
108 pci_device_cfg_read_u8(Eq(&dev), NotNull(), config))
109 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
110 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(
111 Eq(&dev), defaultVal | bridgeEnabled, config))
112 .WillOnce(Return(0));
113
114 EXPECT_CALL(pciMock,
115 pci_device_cfg_read_u8(Eq(&dev), NotNull(), config))
116 .WillOnce(
117 DoAll(SetArgPointee<1>(defaultVal | bridgeEnabled), Return(0)));
118 EXPECT_CALL(pciMock,
119 pci_device_cfg_write_u8(Eq(&dev), defaultVal, config))
120 .WillOnce(Return(0));
121 }
122
Willy Tu8a9de242020-10-30 11:00:21 -0700123 std::unique_ptr<PciBridgeIntf>
124 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const override
Benjamin Faire5aafa52020-06-05 21:04:24 -0700125 {
Willy Tu8a9de242020-10-30 11:00:21 -0700126 return std::make_unique<NuvotonPciBridge>(pci, skipBridgeDisable);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700127 }
128
129 std::string getName() const override
130 {
131 return "Nuvoton"s;
132 }
133
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700134 /* Offset to the config register */
135 static constexpr int config = 0x04;
136 /* Second bit determines whether bridge is enabled */
137 static constexpr std::uint8_t bridgeEnabled = 0x02;
138
Benjamin Faire5aafa52020-06-05 21:04:24 -0700139 private:
140 static constexpr struct pci_id_match match
141 {
Willy Tub487eb42021-09-16 21:44:43 -0700142 0x1050, 0x0750, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0
Benjamin Faire5aafa52020-06-05 21:04:24 -0700143 };
144};
145
146class AspeedDevice : public Device
147{
148 public:
149 const struct pci_id_match* getMatch() const override
150 {
151 return &match;
152 }
153
154 struct pci_device getDevice() const override
155 {
156 struct pci_device dev;
157
158 dev.vendor_id = match.vendor_id;
159 dev.device_id = match.device_id;
160
161 dev.regions[1].is_IO = false;
162 dev.regions[1].base_addr = mockBaseAddr;
163 dev.regions[1].size = mockRegionSize;
164
165 return dev;
166 }
167
Willy Tu8a9de242020-10-30 11:00:21 -0700168 std::unique_ptr<PciBridgeIntf>
169 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const override
Benjamin Faire5aafa52020-06-05 21:04:24 -0700170 {
Willy Tu8a9de242020-10-30 11:00:21 -0700171 return std::make_unique<AspeedPciBridge>(pci, skipBridgeDisable);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700172 }
173
174 std::string getName() const override
175 {
176 return "Aspeed"s;
177 }
178
179 /* Offset to the config region */
180 static constexpr int config = 0x0f000;
181 /* Lower bit determines whether bridge is enabled */
182 static constexpr std::uint8_t bridgeEnabled = 0x01;
183 /* Offset to the MMIO address configuration */
184 static constexpr int bridge = 0x0f004;
185
186 private:
187 static constexpr struct pci_id_match match
188 {
Willy Tub487eb42021-09-16 21:44:43 -0700189 0x1a03, 0x2000, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0
Benjamin Faire5aafa52020-06-05 21:04:24 -0700190 };
191};
192
193NuvotonDevice nuvotonDevice;
194AspeedDevice aspeedDevice;
195
196class PciSetupTest : public testing::TestWithParam<Device*>
197{};
198
199/* Handle device not found */
200TEST_P(PciSetupTest, NotFound)
Benjamin Fair20a18092020-06-08 11:12:21 -0700201{
202 PciAccessMock pciMock;
203
Benjamin Faire5aafa52020-06-05 21:04:24 -0700204 InSequence in;
205
206 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
207 PciIdMatch(GetParam()->getMatch())))
208 .WillOnce(Return(mockIter));
209 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
210 .WillOnce(Return(nullptr));
211 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
212
213 EXPECT_THROW(GetParam()->getBridge(&pciMock), NotFoundException);
214}
215
216/* Test finding device but probe fails */
217TEST_P(PciSetupTest, ProbeFail)
218{
219 PciAccessMock pciMock;
220 struct pci_device dev;
221
222 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
223 PciIdMatch(GetParam()->getMatch())))
224 .WillOnce(Return(mockIter));
225 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
226 .WillOnce(Return(&dev))
227 .WillRepeatedly(Return(nullptr));
228
229 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev))).WillOnce(Return(EFAULT));
230
231 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
232
233 EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
234}
235
236/* Test finding device but mapping fails */
237TEST_P(PciSetupTest, MapFail)
238{
239 PciAccessMock pciMock;
240 struct pci_device dev;
241
242 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
243 PciIdMatch(GetParam()->getMatch())))
244 .WillOnce(Return(mockIter));
245 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
246 .WillOnce(Return(&dev))
247 .WillRepeatedly(Return(nullptr));
248
249 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
250 .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
251
252 EXPECT_CALL(pciMock,
253 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
254 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
255 .WillOnce(Return(EFAULT));
256
257 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
258
259 EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
260}
261
262/* Test finding device but unmapping fails */
263TEST_P(PciSetupTest, UnmapFail)
264{
265 PciAccessMock pciMock;
266 struct pci_device dev;
267 std::vector<std::uint8_t> region(mockRegionSize);
268
269 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
270 PciIdMatch(GetParam()->getMatch())))
271 .WillOnce(Return(mockIter));
272 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
273 .WillOnce(Return(&dev))
274 .WillRepeatedly(Return(nullptr));
275
276 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
277 .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
278
279 EXPECT_CALL(pciMock,
280 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
281 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
282 .WillOnce(DoAll(SetArgPointee<4>(region.data()), Return(0)));
283
284 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
285 EXPECT_CALL(pciMock, pci_device_unmap_range(Eq(&dev), Eq(region.data()),
286 mockRegionSize))
287 .WillOnce(Return(EFAULT));
288
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700289 GetParam()->expectSetup(pciMock, dev);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700290 // This will print an error but not throw
291 GetParam()->getBridge(&pciMock);
292}
293
294/* Create expectations on pciMock for finding device and mapping memory region
295 */
296void expectSetup(PciAccessMock& pciMock, struct pci_device& dev, Device* param,
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700297 std::uint8_t* region, bool deviceExpectations = true)
Benjamin Faire5aafa52020-06-05 21:04:24 -0700298{
299 EXPECT_CALL(pciMock,
300 pci_id_match_iterator_create(PciIdMatch(param->getMatch())))
301 .WillOnce(Return(mockIter));
302 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
303 .WillOnce(Return(&dev))
304 .WillRepeatedly(Return(nullptr));
305
306 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
307 .WillOnce(DoAll(Assign(&dev, param->getDevice()), Return(0)));
308
309 EXPECT_CALL(pciMock,
310 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
311 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
312 .WillOnce(DoAll(SetArgPointee<4>(region), Return(0)));
313
314 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
315 EXPECT_CALL(pciMock,
316 pci_device_unmap_range(Eq(&dev), Eq(region), mockRegionSize))
317 .WillOnce(Return(0));
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700318
Vivekanand Veeracholan55b1a712021-02-18 12:06:37 -0800319 EXPECT_CALL(pciMock, pci_device_enable(Eq(&dev))).Times(1);
320
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700321 if (deviceExpectations)
322 param->expectSetup(pciMock, dev);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700323}
324
325/* Test finding device and mapping memory region */
326TEST_P(PciSetupTest, Success)
327{
328 PciAccessMock pciMock;
329 struct pci_device dev;
330 std::vector<std::uint8_t> region(mockRegionSize);
331
332 expectSetup(pciMock, dev, GetParam(), region.data());
333
334 GetParam()->getBridge(&pciMock);
335}
336
337INSTANTIATE_TEST_SUITE_P(Default, PciSetupTest,
338 ::testing::Values(&nuvotonDevice, &aspeedDevice),
339 [](const testing::TestParamInfo<Device*>& info) {
340 return info.param->getName();
341 });
342
343TEST(NuvotonWriteTest, TooLarge)
344{
345 PciAccessMock pciMock;
346 struct pci_device dev;
347 std::vector<std::uint8_t> region(mockRegionSize);
348 std::vector<std::uint8_t> data(0x4001);
349
350 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
351
352 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
353 EXPECT_THROW(bridge->write(stdplus::span<std::uint8_t>(data)),
354 ToolException);
355}
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);
369 bridge->write(stdplus::span<std::uint8_t>(data));
370
371 EXPECT_THAT(stdplus::span<uint8_t>(&region[0], data.size()),
372 SpanEq(stdplus::span<uint8_t>(data)));
373}
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);
595 EXPECT_THROW(bridge->write(stdplus::span<std::uint8_t>(data)),
596 ToolException);
597}
598
599TEST(AspeedWriteTest, Success)
600{
601 PciAccessMock pciMock;
602 struct pci_device dev;
603 std::vector<std::uint8_t> region(mockRegionSize);
604 std::vector<std::uint8_t> data(0x10000);
605
606 std::generate(data.begin(), data.end(), std::rand);
607
608 expectSetup(pciMock, dev, &aspeedDevice, region.data());
609
610 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
611 bridge->write(stdplus::span<std::uint8_t>(data));
612
613 EXPECT_THAT(stdplus::span<uint8_t>(&region[0x10000], data.size()),
614 SpanEq(stdplus::span<uint8_t>(data)));
615}
616
617TEST(AspeedConfigureTest, Success)
618{
619 PciAccessMock pciMock;
620 struct pci_device dev;
621 std::vector<std::uint8_t> region(mockRegionSize);
622 ipmi_flash::PciConfigResponse config{0x123bea51};
623
624 expectSetup(pciMock, dev, &aspeedDevice, region.data());
625
626 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
627 bridge->configure(config);
628
629 auto configSpan = stdplus::raw::asSpan<uint8_t>(config);
630 EXPECT_THAT(
631 stdplus::span<uint8_t>(&region[AspeedDevice::bridge], sizeof(config)),
632 SpanEq(configSpan));
633}
634
635TEST(AspeedDataLengthTest, Success)
636{
637 PciAccessMock pciMock;
638 struct pci_device dev;
639 std::vector<std::uint8_t> region(mockRegionSize);
640
641 expectSetup(pciMock, dev, &aspeedDevice, region.data());
642
643 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
644 EXPECT_EQ(bridge->getDataLength(), 0x10000);
645}
646
647/* Make sure config region is left alone if the bridge is already enabled */
648TEST(AspeedBridgeTest, AlreadyEnabledSuccess)
649{
650 PciAccessMock pciMock;
651 struct pci_device dev;
652 std::vector<std::uint8_t> region(mockRegionSize);
653
654 constexpr std::uint8_t defaultVal = 0x42;
655
656 region[AspeedDevice::config] = defaultVal | AspeedDevice::bridgeEnabled;
657
658 expectSetup(pciMock, dev, &aspeedDevice, region.data());
659
660 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
661
662 {
663 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
664 enabledRegion[AspeedDevice::config] =
665 defaultVal | AspeedDevice::bridgeEnabled;
666 EXPECT_THAT(region, ContainerEq(enabledRegion));
667 }
668
669 bridge.reset();
670
671 {
672 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
673 disabledRegion[AspeedDevice::config] = defaultVal;
674 EXPECT_THAT(region, ContainerEq(disabledRegion));
675 }
676}
677
Willy Tu8a9de242020-10-30 11:00:21 -0700678/* Make sure the config region remains the same even after cleanup if
679 * skipBridgeDisable is true */
680TEST(AspeedBridgeTest, SkipDisable)
681{
682 PciAccessMock pciMock;
683 struct pci_device dev;
684 std::vector<std::uint8_t> region(mockRegionSize);
685
686 constexpr std::uint8_t defaultVal = 0x42;
687
688 region[AspeedDevice::config] = defaultVal | AspeedDevice::bridgeEnabled;
689
690 expectSetup(pciMock, dev, &aspeedDevice, region.data());
691
692 /* Setting skipBridgeDisable to true */
693 std::unique_ptr<PciBridgeIntf> bridge =
694 aspeedDevice.getBridge(&pciMock, true);
695
696 {
697 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
698 enabledRegion[AspeedDevice::config] =
699 defaultVal | AspeedDevice::bridgeEnabled;
700 EXPECT_THAT(region, ContainerEq(enabledRegion));
701 }
702
703 bridge.reset();
704
705 {
706 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
707 disabledRegion[AspeedDevice::config] =
708 defaultVal | AspeedDevice::bridgeEnabled;
709 EXPECT_THAT(region, ContainerEq(disabledRegion));
710 }
711}
712
Benjamin Faire5aafa52020-06-05 21:04:24 -0700713/* Make sure the bridge gets enabled when needed */
714TEST(AspeedBridgeTest, NotEnabledSuccess)
715{
716 PciAccessMock pciMock;
717 struct pci_device dev;
718 std::vector<std::uint8_t> region(mockRegionSize);
719
720 constexpr std::uint8_t defaultVal = 0x42;
721
722 region[AspeedDevice::config] = defaultVal;
723
724 expectSetup(pciMock, dev, &aspeedDevice, region.data());
725
726 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
727
728 {
729 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
730 enabledRegion[AspeedDevice::config] =
731 defaultVal | AspeedDevice::bridgeEnabled;
732 EXPECT_THAT(region, ContainerEq(enabledRegion));
733 }
734
735 bridge.reset();
736
737 {
738 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
739 disabledRegion[AspeedDevice::config] = defaultVal;
740 EXPECT_THAT(region, ContainerEq(disabledRegion));
741 }
Benjamin Fair20a18092020-06-08 11:12:21 -0700742}
743
744} // namespace
745} // namespace host_tool