1 /* 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 17 #include "internal_sys_mock.hpp" 18 #include "pci.hpp" 19 #include "pciaccess_mock.hpp" 20 #include "tool_errors.hpp" 21 22 #include <stdplus/raw.hpp> 23 24 #include <algorithm> 25 #include <cstdlib> 26 #include <string> 27 #include <vector> 28 29 #include <gtest/gtest.h> 30 31 namespace host_tool 32 { 33 namespace 34 { 35 36 using namespace std::string_literals; 37 38 using ::testing::Assign; 39 using ::testing::ContainerEq; 40 using ::testing::DoAll; 41 using ::testing::Each; 42 using ::testing::Eq; 43 using ::testing::InSequence; 44 using ::testing::NotNull; 45 using ::testing::Return; 46 using ::testing::SetArgPointee; 47 48 // TODO: switch to ConainerEq for C++20 49 MATCHER_P(SpanEq, s, "") 50 { 51 return arg.size() == s.size() && !memcmp(arg.data(), s.data(), s.size()); 52 } 53 54 MATCHER_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 61 pci_device_iterator* mockIter = reinterpret_cast<pci_device_iterator*>(0x42); 62 63 constexpr pciaddr_t mockBaseAddr = 0xdeadbeef; 64 constexpr pciaddr_t mockRegionSize = 0x20000; 65 66 class Device 67 { 68 public: 69 virtual ~Device() = default; 70 virtual const struct pci_id_match* getMatch() const = 0; 71 virtual struct pci_device getDevice() const = 0; 72 virtual void expectSetup(PciAccessMock&, const struct pci_device&) const {}; 73 virtual std::unique_ptr<PciBridgeIntf> 74 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const = 0; 75 virtual std::string getName() const = 0; 76 }; 77 78 class 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 100 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 123 std::unique_ptr<PciBridgeIntf> 124 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const override 125 { 126 return std::make_unique<NuvotonPciBridge>(pci, skipBridgeDisable); 127 } 128 129 std::string getName() const override 130 { 131 return "Nuvoton"s; 132 } 133 134 /* 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 139 private: 140 static constexpr struct pci_id_match match 141 { 142 0x1050, 0x0750, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0 143 }; 144 }; 145 146 class 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 168 std::unique_ptr<PciBridgeIntf> 169 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const override 170 { 171 return std::make_unique<AspeedPciBridge>(pci, skipBridgeDisable); 172 } 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 { 189 0x1a03, 0x2000, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0 190 }; 191 }; 192 193 NuvotonDevice nuvotonDevice; 194 AspeedDevice aspeedDevice; 195 196 class PciSetupTest : public testing::TestWithParam<Device*> 197 {}; 198 199 /* Handle device not found */ 200 TEST_P(PciSetupTest, NotFound) 201 { 202 PciAccessMock pciMock; 203 204 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 */ 217 TEST_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 */ 237 TEST_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 */ 263 TEST_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 289 GetParam()->expectSetup(pciMock, dev); 290 // 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 */ 296 void expectSetup(PciAccessMock& pciMock, struct pci_device& dev, Device* param, 297 std::uint8_t* region, bool deviceExpectations = true) 298 { 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)); 318 319 EXPECT_CALL(pciMock, pci_device_enable(Eq(&dev))).Times(1); 320 321 if (deviceExpectations) 322 param->expectSetup(pciMock, dev); 323 } 324 325 /* Test finding device and mapping memory region */ 326 TEST_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 337 INSTANTIATE_TEST_SUITE_P(Default, PciSetupTest, 338 ::testing::Values(&nuvotonDevice, &aspeedDevice), 339 [](const testing::TestParamInfo<Device*>& info) { 340 return info.param->getName(); 341 }); 342 343 TEST(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 357 TEST(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>(®ion[0], data.size()), 372 SpanEq(stdplus::span<uint8_t>(data))); 373 } 374 375 TEST(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 391 TEST(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 403 /* Make sure config register is left alone if the bridge is already enabled */ 404 TEST(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 */ 438 TEST(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 */ 455 TEST(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 */ 479 TEST(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 */ 511 TEST(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 */ 548 TEST(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 558 /* Make sure it skips the disable bridge call when skipBridgeDisable is true */ 559 TEST(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 585 TEST(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 599 TEST(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>(®ion[0x10000], data.size()), 614 SpanEq(stdplus::span<uint8_t>(data))); 615 } 616 617 TEST(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>(®ion[AspeedDevice::bridge], sizeof(config)), 632 SpanEq(configSpan)); 633 } 634 635 TEST(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 */ 648 TEST(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 678 /* Make sure the config region remains the same even after cleanup if 679 * skipBridgeDisable is true */ 680 TEST(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 713 /* Make sure the bridge gets enabled when needed */ 714 TEST(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 } 742 } 743 744 } // namespace 745 } // namespace host_tool 746