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