blob: 4a45468d12250bc02b3501c99920363266071b40 [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;
Benjamin Fairc1a30c02020-06-09 11:46:34 -070072 virtual void expectSetup(PciAccessMock& pciMock,
73 const struct pci_device& dev) const {};
Benjamin Faire5aafa52020-06-05 21:04:24 -070074 virtual std::unique_ptr<PciBridgeIntf> getBridge(PciAccess* pci) const = 0;
75 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
Benjamin Faire5aafa52020-06-05 21:04:24 -0700123 std::unique_ptr<PciBridgeIntf> getBridge(PciAccess* pci) const override
124 {
125 return std::make_unique<NuvotonPciBridge>(pci);
126 }
127
128 std::string getName() const override
129 {
130 return "Nuvoton"s;
131 }
132
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700133 /* Offset to the config register */
134 static constexpr int config = 0x04;
135 /* Second bit determines whether bridge is enabled */
136 static constexpr std::uint8_t bridgeEnabled = 0x02;
137
Benjamin Faire5aafa52020-06-05 21:04:24 -0700138 private:
139 static constexpr struct pci_id_match match
140 {
141 0x1050, 0x0750, PCI_MATCH_ANY, PCI_MATCH_ANY
142 };
143};
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
167 std::unique_ptr<PciBridgeIntf> getBridge(PciAccess* pci) const override
168 {
169 return std::make_unique<AspeedPciBridge>(pci);
170 }
171
172 std::string getName() const override
173 {
174 return "Aspeed"s;
175 }
176
177 /* Offset to the config region */
178 static constexpr int config = 0x0f000;
179 /* Lower bit determines whether bridge is enabled */
180 static constexpr std::uint8_t bridgeEnabled = 0x01;
181 /* Offset to the MMIO address configuration */
182 static constexpr int bridge = 0x0f004;
183
184 private:
185 static constexpr struct pci_id_match match
186 {
187 0x1a03, 0x2000, PCI_MATCH_ANY, PCI_MATCH_ANY
188 };
189};
190
191NuvotonDevice nuvotonDevice;
192AspeedDevice aspeedDevice;
193
194class PciSetupTest : public testing::TestWithParam<Device*>
195{};
196
197/* Handle device not found */
198TEST_P(PciSetupTest, NotFound)
Benjamin Fair20a18092020-06-08 11:12:21 -0700199{
200 PciAccessMock pciMock;
201
Benjamin Faire5aafa52020-06-05 21:04:24 -0700202 InSequence in;
203
204 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
205 PciIdMatch(GetParam()->getMatch())))
206 .WillOnce(Return(mockIter));
207 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
208 .WillOnce(Return(nullptr));
209 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
210
211 EXPECT_THROW(GetParam()->getBridge(&pciMock), NotFoundException);
212}
213
214/* Test finding device but probe fails */
215TEST_P(PciSetupTest, ProbeFail)
216{
217 PciAccessMock pciMock;
218 struct pci_device dev;
219
220 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
221 PciIdMatch(GetParam()->getMatch())))
222 .WillOnce(Return(mockIter));
223 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
224 .WillOnce(Return(&dev))
225 .WillRepeatedly(Return(nullptr));
226
227 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev))).WillOnce(Return(EFAULT));
228
229 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
230
231 EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
232}
233
234/* Test finding device but mapping fails */
235TEST_P(PciSetupTest, MapFail)
236{
237 PciAccessMock pciMock;
238 struct pci_device dev;
239
240 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
241 PciIdMatch(GetParam()->getMatch())))
242 .WillOnce(Return(mockIter));
243 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
244 .WillOnce(Return(&dev))
245 .WillRepeatedly(Return(nullptr));
246
247 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
248 .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
249
250 EXPECT_CALL(pciMock,
251 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
252 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
253 .WillOnce(Return(EFAULT));
254
255 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
256
257 EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
258}
259
260/* Test finding device but unmapping fails */
261TEST_P(PciSetupTest, UnmapFail)
262{
263 PciAccessMock pciMock;
264 struct pci_device dev;
265 std::vector<std::uint8_t> region(mockRegionSize);
266
267 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
268 PciIdMatch(GetParam()->getMatch())))
269 .WillOnce(Return(mockIter));
270 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
271 .WillOnce(Return(&dev))
272 .WillRepeatedly(Return(nullptr));
273
274 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
275 .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
276
277 EXPECT_CALL(pciMock,
278 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
279 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
280 .WillOnce(DoAll(SetArgPointee<4>(region.data()), Return(0)));
281
282 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
283 EXPECT_CALL(pciMock, pci_device_unmap_range(Eq(&dev), Eq(region.data()),
284 mockRegionSize))
285 .WillOnce(Return(EFAULT));
286
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700287 GetParam()->expectSetup(pciMock, dev);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700288 // This will print an error but not throw
289 GetParam()->getBridge(&pciMock);
290}
291
292/* Create expectations on pciMock for finding device and mapping memory region
293 */
294void expectSetup(PciAccessMock& pciMock, struct pci_device& dev, Device* param,
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700295 std::uint8_t* region, bool deviceExpectations = true)
Benjamin Faire5aafa52020-06-05 21:04:24 -0700296{
297 EXPECT_CALL(pciMock,
298 pci_id_match_iterator_create(PciIdMatch(param->getMatch())))
299 .WillOnce(Return(mockIter));
300 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
301 .WillOnce(Return(&dev))
302 .WillRepeatedly(Return(nullptr));
303
304 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
305 .WillOnce(DoAll(Assign(&dev, param->getDevice()), Return(0)));
306
307 EXPECT_CALL(pciMock,
308 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
309 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
310 .WillOnce(DoAll(SetArgPointee<4>(region), Return(0)));
311
312 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
313 EXPECT_CALL(pciMock,
314 pci_device_unmap_range(Eq(&dev), Eq(region), mockRegionSize))
315 .WillOnce(Return(0));
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700316
317 if (deviceExpectations)
318 param->expectSetup(pciMock, dev);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700319}
320
321/* Test finding device and mapping memory region */
322TEST_P(PciSetupTest, Success)
323{
324 PciAccessMock pciMock;
325 struct pci_device dev;
326 std::vector<std::uint8_t> region(mockRegionSize);
327
328 expectSetup(pciMock, dev, GetParam(), region.data());
329
330 GetParam()->getBridge(&pciMock);
331}
332
333INSTANTIATE_TEST_SUITE_P(Default, PciSetupTest,
334 ::testing::Values(&nuvotonDevice, &aspeedDevice),
335 [](const testing::TestParamInfo<Device*>& info) {
336 return info.param->getName();
337 });
338
339TEST(NuvotonWriteTest, TooLarge)
340{
341 PciAccessMock pciMock;
342 struct pci_device dev;
343 std::vector<std::uint8_t> region(mockRegionSize);
344 std::vector<std::uint8_t> data(0x4001);
345
346 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
347
348 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
349 EXPECT_THROW(bridge->write(stdplus::span<std::uint8_t>(data)),
350 ToolException);
351}
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);
365 bridge->write(stdplus::span<std::uint8_t>(data));
366
367 EXPECT_THAT(stdplus::span<uint8_t>(&region[0], data.size()),
368 SpanEq(stdplus::span<uint8_t>(data)));
369}
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
Benjamin Faire5aafa52020-06-05 21:04:24 -0700554TEST(AspeedWriteTest, TooLarge)
555{
556 PciAccessMock pciMock;
557 struct pci_device dev;
558 std::vector<std::uint8_t> region(mockRegionSize);
559 std::vector<std::uint8_t> data(0x10001);
560
561 expectSetup(pciMock, dev, &aspeedDevice, region.data());
562
563 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
564 EXPECT_THROW(bridge->write(stdplus::span<std::uint8_t>(data)),
565 ToolException);
566}
567
568TEST(AspeedWriteTest, Success)
569{
570 PciAccessMock pciMock;
571 struct pci_device dev;
572 std::vector<std::uint8_t> region(mockRegionSize);
573 std::vector<std::uint8_t> data(0x10000);
574
575 std::generate(data.begin(), data.end(), std::rand);
576
577 expectSetup(pciMock, dev, &aspeedDevice, region.data());
578
579 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
580 bridge->write(stdplus::span<std::uint8_t>(data));
581
582 EXPECT_THAT(stdplus::span<uint8_t>(&region[0x10000], data.size()),
583 SpanEq(stdplus::span<uint8_t>(data)));
584}
585
586TEST(AspeedConfigureTest, Success)
587{
588 PciAccessMock pciMock;
589 struct pci_device dev;
590 std::vector<std::uint8_t> region(mockRegionSize);
591 ipmi_flash::PciConfigResponse config{0x123bea51};
592
593 expectSetup(pciMock, dev, &aspeedDevice, region.data());
594
595 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
596 bridge->configure(config);
597
598 auto configSpan = stdplus::raw::asSpan<uint8_t>(config);
599 EXPECT_THAT(
600 stdplus::span<uint8_t>(&region[AspeedDevice::bridge], sizeof(config)),
601 SpanEq(configSpan));
602}
603
604TEST(AspeedDataLengthTest, Success)
605{
606 PciAccessMock pciMock;
607 struct pci_device dev;
608 std::vector<std::uint8_t> region(mockRegionSize);
609
610 expectSetup(pciMock, dev, &aspeedDevice, region.data());
611
612 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
613 EXPECT_EQ(bridge->getDataLength(), 0x10000);
614}
615
616/* Make sure config region is left alone if the bridge is already enabled */
617TEST(AspeedBridgeTest, AlreadyEnabledSuccess)
618{
619 PciAccessMock pciMock;
620 struct pci_device dev;
621 std::vector<std::uint8_t> region(mockRegionSize);
622
623 constexpr std::uint8_t defaultVal = 0x42;
624
625 region[AspeedDevice::config] = defaultVal | AspeedDevice::bridgeEnabled;
626
627 expectSetup(pciMock, dev, &aspeedDevice, region.data());
628
629 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
630
631 {
632 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
633 enabledRegion[AspeedDevice::config] =
634 defaultVal | AspeedDevice::bridgeEnabled;
635 EXPECT_THAT(region, ContainerEq(enabledRegion));
636 }
637
638 bridge.reset();
639
640 {
641 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
642 disabledRegion[AspeedDevice::config] = defaultVal;
643 EXPECT_THAT(region, ContainerEq(disabledRegion));
644 }
645}
646
647/* Make sure the bridge gets enabled when needed */
648TEST(AspeedBridgeTest, NotEnabledSuccess)
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;
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 }
Benjamin Fair20a18092020-06-08 11:12:21 -0700676}
677
678} // namespace
679} // namespace host_tool