1// Copyright 2018 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <stdio.h> 6#include <stdlib.h> 7 8#include <fbl/alloc_checker.h> 9#include <fbl/unique_ptr.h> 10#include <unittest/unittest.h> 11#include <zircon/device/ram-nand.h> 12#include <zircon/process.h> 13 14#include "fake-ddk.h" 15#include "ram-nand.h" 16 17namespace { 18 19constexpr int kPageSize = 4096; 20constexpr int kOobSize = 4; 21constexpr int kBlockSize = 4; 22constexpr int kNumBlocks = 5; 23constexpr int kNumPages = kBlockSize * kNumBlocks; 24 25ram_nand_info_t BuildConfig() { 26 return ram_nand_info_t{ 27 .vmo = 0, 28 .nand_info = {4096, 4, 5, 6, 0, NAND_CLASS_FTL, {}}, 29 .export_nand_config = false, 30 .export_partition_map = false, 31 .bad_block_config = {}, 32 .extra_partition_config_count = 0, 33 .extra_partition_config = {}, 34 .partition_map = {}, 35 }; 36} 37 38bool TrivialLifetimeTest() { 39 BEGIN_TEST; 40 NandParams params(kPageSize, kBlockSize, kNumBlocks, 6, 0); // 6 bits of ECC, no OOB. 41 char name[NAME_MAX]; 42 { 43 NandDevice device(params); 44 45 ASSERT_EQ(ZX_OK, device.Init(name, zx::vmo())); 46 EXPECT_EQ(0, strncmp("ram-nand-0", name, NAME_MAX)); 47 } 48 { 49 NandDevice device(params); 50 51 ASSERT_EQ(ZX_OK, device.Init(name, zx::vmo())); 52 EXPECT_EQ(0, strncmp("ram-nand-1", name, NAME_MAX)); 53 } 54 END_TEST; 55} 56 57bool DdkLifetimeTest() { 58 BEGIN_TEST; 59 NandParams params(kPageSize, kBlockSize, kNumBlocks, 6, 0); // 6 bits of ECC, no OOB. 60 NandDevice* device(new NandDevice(params, fake_ddk::kFakeParent)); 61 62 fake_ddk::Bind ddk; 63 ASSERT_EQ(ZX_OK, device->Bind(BuildConfig())); 64 device->DdkUnbind(); 65 EXPECT_TRUE(ddk.Ok()); 66 67 // This should delete the object, which means this test should not leak. 68 device->DdkRelease(); 69 END_TEST; 70} 71 72fbl::unique_ptr<NandDevice> CreateDevice(size_t* operation_size) { 73 NandParams params(kPageSize, kBlockSize, kNumBlocks, 6, kOobSize); // 6 bits of ECC. 74 fbl::AllocChecker checker; 75 fbl::unique_ptr<NandDevice> device(new (&checker) NandDevice(params)); 76 if (!checker.check()) { 77 return nullptr; 78 } 79 80 if (operation_size) { 81 nand_info_t info; 82 device->Query(&info, operation_size); 83 } 84 85 char name[NAME_MAX]; 86 if (device->Init(name, zx::vmo()) != ZX_OK) { 87 return nullptr; 88 } 89 return fbl::move(device); 90} 91 92bool BasicDeviceProtocolTest() { 93 BEGIN_TEST; 94 NandParams params(kPageSize, kBlockSize, kNumBlocks, 6, 0); // 6 bits of ECC, no OOB. 95 NandDevice device(params); 96 97 char name[NAME_MAX]; 98 ASSERT_EQ(ZX_OK, device.Init(name, zx::vmo())); 99 100 ASSERT_EQ(kPageSize * kNumPages, device.DdkGetSize()); 101 102 device.DdkUnbind(); 103 104 ASSERT_EQ(ZX_ERR_BAD_STATE, 105 device.DdkIoctl(IOCTL_RAM_NAND_UNLINK, nullptr, 0, nullptr, 0, nullptr)); 106 END_TEST; 107} 108 109bool UnlinkTest() { 110 BEGIN_TEST; 111 fbl::unique_ptr<NandDevice> device = CreateDevice(nullptr); 112 ASSERT_TRUE(device); 113 114 ASSERT_EQ(ZX_OK, device->DdkIoctl(IOCTL_RAM_NAND_UNLINK, nullptr, 0, nullptr, 0, nullptr)); 115 116 // The device is "dead" now. 117 ASSERT_EQ(ZX_ERR_BAD_STATE, 118 device->DdkIoctl(IOCTL_RAM_NAND_UNLINK, nullptr, 0, nullptr, 0, nullptr)); 119 END_TEST; 120} 121 122bool QueryTest() { 123 BEGIN_TEST; 124 NandParams params(kPageSize, kBlockSize, kNumBlocks, 6, 8); // 6 bits of ECC, 8 OOB bytes. 125 NandDevice device(params); 126 127 nand_info_t info; 128 size_t operation_size; 129 device.Query(&info, &operation_size); 130 ASSERT_EQ(0, memcmp(&info, ¶ms, sizeof(info))); 131 ASSERT_GT(operation_size, sizeof(nand_op_t)); 132 END_TEST; 133} 134 135// Tests setting and getting bad blocks. 136bool FactoryBadBlockListTest() { 137 BEGIN_TEST; 138 fbl::unique_ptr<NandDevice> device = CreateDevice(nullptr); 139 ASSERT_TRUE(device); 140 141 uint32_t bad_blocks[] = {1, 3, 5}; 142 ASSERT_EQ(ZX_ERR_NOT_SUPPORTED, 143 device->DdkIoctl(IOCTL_RAM_NAND_SET_BAD_BLOCKS, bad_blocks, sizeof(bad_blocks), 144 nullptr, 0, nullptr)); 145 146 uint32_t result[4]; 147 uint32_t num_bad_blocks; 148 device->GetFactoryBadBlockList(result, sizeof(result), &num_bad_blocks); 149 ASSERT_EQ(0, num_bad_blocks); 150 END_TEST; 151} 152 153// Data to be pre-pended to a nand_op_t issued to the device. 154struct OpHeader { 155 class Operation* operation; 156 class NandTest* test; 157}; 158 159// Wrapper for a nand_op_t. 160class Operation { 161 public: 162 explicit Operation(size_t op_size, NandTest* test = 0) 163 : op_size_(op_size + sizeof(OpHeader)), test_(test) {} 164 ~Operation() { 165 if (mapped_addr_) { 166 zx_vmar_unmap(zx_vmar_root_self(), reinterpret_cast<uintptr_t>(mapped_addr_), 167 buffer_size_); 168 } 169 } 170 171 // Accessors for the memory represented by the operation's vmo. 172 size_t buffer_size() const { return buffer_size_; } 173 char* buffer() const { return mapped_addr_; } 174 175 // Creates a vmo and sets the handle on the nand_op_t. 176 bool SetDataVmo(); 177 bool SetOobVmo(); 178 179 nand_op_t* GetOperation(); 180 181 void OnCompletion(zx_status_t status) { 182 status_ = status; 183 completed_ = true; 184 } 185 186 bool completed() const { return completed_; } 187 zx_status_t status() const { return status_; } 188 189 private: 190 zx_handle_t GetVmo(); 191 void CreateOperation(); 192 193 zx::vmo vmo_; 194 char* mapped_addr_ = nullptr; 195 size_t op_size_; 196 NandTest* test_; 197 zx_status_t status_ = ZX_ERR_ACCESS_DENIED; 198 bool completed_ = false; 199 static constexpr size_t buffer_size_ = (kPageSize + kOobSize) * kNumPages; 200 fbl::unique_ptr<char[]> raw_buffer_; 201 DISALLOW_COPY_ASSIGN_AND_MOVE(Operation); 202}; 203 204bool Operation::SetDataVmo() { 205 nand_op_t* operation = GetOperation(); 206 if (!operation) { 207 return false; 208 } 209 operation->rw.data_vmo = GetVmo(); 210 return operation->rw.data_vmo != ZX_HANDLE_INVALID; 211} 212 213bool Operation::SetOobVmo() { 214 nand_op_t* operation = GetOperation(); 215 if (!operation) { 216 return false; 217 } 218 operation->rw.oob_vmo = GetVmo(); 219 return operation->rw.oob_vmo != ZX_HANDLE_INVALID; 220} 221 222nand_op_t* Operation::GetOperation() { 223 if (!raw_buffer_) { 224 CreateOperation(); 225 } 226 return reinterpret_cast<nand_op_t*>(raw_buffer_.get() + sizeof(OpHeader)); 227} 228 229zx_handle_t Operation::GetVmo() { 230 if (vmo_.is_valid()) { 231 return vmo_.get(); 232 } 233 234 zx_status_t status = zx::vmo::create(buffer_size_, 0, &vmo_); 235 if (status != ZX_OK) { 236 return ZX_HANDLE_INVALID; 237 } 238 239 uintptr_t address; 240 status = zx_vmar_map(zx_vmar_root_self(), 241 ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 242 0, vmo_.get(), 0, buffer_size_, &address); 243 if (status != ZX_OK) { 244 return ZX_HANDLE_INVALID; 245 } 246 mapped_addr_ = reinterpret_cast<char*>(address); 247 return vmo_.get(); 248} 249 250void Operation::CreateOperation() { 251 fbl::AllocChecker checker; 252 raw_buffer_.reset(new (&checker) char[op_size_]); 253 if (!checker.check()) { 254 return; 255 } 256 257 memset(raw_buffer_.get(), 0, op_size_); 258 OpHeader* header = reinterpret_cast<OpHeader*>(raw_buffer_.get()); 259 header->operation = this; 260 header->test = test_; 261} 262 263// Provides control primitives for tests that issue IO requests to the device. 264class NandTest { 265 public: 266 NandTest() {} 267 ~NandTest() {} 268 269 static void CompletionCb(nand_op_t* op, zx_status_t status) { 270 OpHeader* header = 271 reinterpret_cast<OpHeader*>(reinterpret_cast<char*>(op) - sizeof(OpHeader)); 272 273 header->operation->OnCompletion(status); 274 header->test->num_completed_++; 275 sync_completion_signal(&header->test->event_); 276 } 277 278 bool Wait() { 279 zx_status_t status = sync_completion_wait(&event_, ZX_SEC(5)); 280 sync_completion_reset(&event_); 281 return status == ZX_OK; 282 } 283 284 bool WaitFor(int desired) { 285 while (num_completed_ < desired) { 286 if (!Wait()) { 287 return false; 288 } 289 } 290 return true; 291 } 292 293 private: 294 sync_completion_t event_; 295 int num_completed_ = 0; 296 DISALLOW_COPY_ASSIGN_AND_MOVE(NandTest); 297}; 298 299// Tests trivial attempts to queue one operation. 300bool QueueOneTest() { 301 BEGIN_TEST; 302 303 size_t op_size; 304 fbl::unique_ptr<NandDevice> device = CreateDevice(&op_size); 305 ASSERT_TRUE(device); 306 307 NandTest test; 308 Operation operation(op_size, &test); 309 310 nand_op_t* op = operation.GetOperation(); 311 ASSERT_TRUE(op); 312 313 op->rw.command = NAND_OP_WRITE; 314 op->completion_cb = &NandTest::CompletionCb; 315 device->Queue(op); 316 317 ASSERT_TRUE(test.Wait()); 318 ASSERT_EQ(ZX_ERR_OUT_OF_RANGE, operation.status()); 319 320 op->rw.length = 1; 321 device->Queue(op); 322 ASSERT_TRUE(test.Wait()); 323 ASSERT_EQ(ZX_ERR_BAD_HANDLE, operation.status()); 324 325 op->rw.offset_nand = kNumPages; 326 device->Queue(op); 327 ASSERT_TRUE(test.Wait()); 328 ASSERT_EQ(ZX_ERR_OUT_OF_RANGE, operation.status()); 329 330 ASSERT_TRUE(operation.SetDataVmo()); 331 332 op->rw.offset_nand = kNumPages - 1; 333 device->Queue(op); 334 ASSERT_TRUE(test.Wait()); 335 ASSERT_EQ(ZX_OK, operation.status()); 336 337 END_TEST; 338} 339 340// Verifies that the buffer pointed to by the operation's vmo contains the given 341// pattern for the desired number of pages, skipping the pages before start. 342bool CheckPattern(uint8_t what, int start, int num_pages, const Operation& operation) { 343 const char* buffer = operation.buffer() + kPageSize * start; 344 for (int i = 0; i < kPageSize * num_pages; i++) { 345 if (static_cast<uint8_t>(buffer[i]) != what) { 346 return false; 347 } 348 } 349 return true; 350} 351 352// Prepares the operation to write num_pages starting at offset. 353void SetForWrite(int offset, int num_pages, Operation* operation) { 354 nand_op_t* op = operation->GetOperation(); 355 op->rw.command = NAND_OP_WRITE; 356 op->rw.length = num_pages; 357 op->rw.offset_nand = offset; 358 op->completion_cb = &NandTest::CompletionCb; 359} 360 361// Prepares the operation to read num_pages starting at offset. 362void SetForRead(int offset, int num_pages, Operation* operation) { 363 nand_op_t* op = operation->GetOperation(); 364 op->rw.command = NAND_OP_READ; 365 op->rw.length = num_pages; 366 op->rw.offset_nand = offset; 367 op->completion_cb = &NandTest::CompletionCb; 368} 369 370bool ReadWriteTest() { 371 BEGIN_TEST; 372 373 size_t op_size; 374 fbl::unique_ptr<NandDevice> device = CreateDevice(&op_size); 375 ASSERT_TRUE(device); 376 377 NandTest test; 378 Operation operation(op_size, &test); 379 ASSERT_TRUE(operation.SetDataVmo()); 380 memset(operation.buffer(), 0x55, operation.buffer_size()); 381 382 nand_op_t* op = operation.GetOperation(); 383 op->rw.corrected_bit_flips = 125; 384 385 SetForWrite(4, 4, &operation); 386 device->Queue(op); 387 388 ASSERT_TRUE(test.Wait()); 389 ASSERT_EQ(ZX_OK, operation.status()); 390 ASSERT_EQ(125, op->rw.corrected_bit_flips); // Doesn't modify the value. 391 392 op->rw.command = NAND_OP_READ; 393 memset(operation.buffer(), 0, operation.buffer_size()); 394 395 device->Queue(op); 396 ASSERT_TRUE(test.Wait()); 397 ASSERT_EQ(ZX_OK, operation.status()); 398 ASSERT_EQ(0, op->rw.corrected_bit_flips); 399 ASSERT_TRUE(CheckPattern(0x55, 0, 4, operation)); 400 401 END_TEST; 402} 403 404// Tests that a new device is filled with 0xff (as a new nand chip). 405bool NewChipTest() { 406 BEGIN_TEST; 407 408 size_t op_size; 409 fbl::unique_ptr<NandDevice> device = CreateDevice(&op_size); 410 ASSERT_TRUE(device); 411 412 NandTest test; 413 Operation operation(op_size, &test); 414 ASSERT_TRUE(operation.SetDataVmo()); 415 ASSERT_TRUE(operation.SetOobVmo()); 416 memset(operation.buffer(), 0x55, operation.buffer_size()); 417 418 nand_op_t* op = operation.GetOperation(); 419 op->rw.corrected_bit_flips = 125; 420 421 SetForRead(0, kNumPages, &operation); 422 op->rw.offset_oob_vmo = kNumPages; 423 device->Queue(op); 424 425 ASSERT_TRUE(test.Wait()); 426 ASSERT_EQ(ZX_OK, operation.status()); 427 ASSERT_EQ(0, op->rw.corrected_bit_flips); 428 429 ASSERT_TRUE(CheckPattern(0xff, 0, kNumPages, operation)); 430 431 // Verify OOB area. 432 memset(operation.buffer(), 0xff, kOobSize * kNumPages); 433 ASSERT_EQ(0, 434 memcmp(operation.buffer() + kPageSize * kNumPages, operation.buffer(), 435 kOobSize * kNumPages)); 436 437 END_TEST; 438} 439 440// Tests serialization of multiple reads and writes. 441bool QueueMultipleTest() { 442 BEGIN_TEST; 443 444 size_t op_size; 445 fbl::unique_ptr<NandDevice> device = CreateDevice(&op_size); 446 ASSERT_TRUE(device); 447 448 NandTest test; 449 fbl::unique_ptr<Operation> operations[10]; 450 for (int i = 0; i < 10; i++) { 451 fbl::AllocChecker checker; 452 operations[i].reset(new (&checker) Operation(op_size, &test)); 453 ASSERT_TRUE(checker.check()); 454 Operation& operation = *(operations[i].get()); 455 ASSERT_TRUE(operation.SetDataVmo()); 456 memset(operation.buffer(), i + 30, operation.buffer_size()); 457 } 458 459 SetForWrite(0, 1, operations[0].get()); // 0 x x x x x 460 SetForWrite(1, 3, operations[1].get()); // 0 1 1 1 x x 461 SetForRead(0, 4, operations[2].get()); 462 SetForWrite(4, 2, operations[3].get()); // 0 1 1 1 3 3 463 SetForRead(2, 4, operations[4].get()); 464 SetForWrite(2, 2, operations[5].get()); // 0 1 5 5 3 3 465 SetForRead(0, 4, operations[6].get()); 466 SetForWrite(0, 4, operations[7].get()); // 7 7 7 7 3 3 467 SetForRead(2, 4, operations[8].get()); 468 SetForRead(0, 2, operations[9].get()); 469 470 for (const auto& operation : operations) { 471 nand_op_t* op = operation->GetOperation(); 472 device->Queue(op); 473 } 474 475 ASSERT_TRUE(test.WaitFor(10)); 476 477 for (const auto& operation : operations) { 478 ASSERT_EQ(ZX_OK, operation->status()); 479 ASSERT_TRUE(operation->completed()); 480 } 481 482 ASSERT_TRUE(CheckPattern(30, 0, 1, *(operations[2].get()))); 483 ASSERT_TRUE(CheckPattern(31, 1, 3, *(operations[2].get()))); 484 485 ASSERT_TRUE(CheckPattern(31, 0, 2, *(operations[4].get()))); 486 ASSERT_TRUE(CheckPattern(33, 2, 2, *(operations[4].get()))); 487 488 ASSERT_TRUE(CheckPattern(30, 0, 1, *(operations[6].get()))); 489 ASSERT_TRUE(CheckPattern(31, 1, 1, *(operations[6].get()))); 490 ASSERT_TRUE(CheckPattern(35, 2, 2, *(operations[6].get()))); 491 492 ASSERT_TRUE(CheckPattern(37, 0, 2, *(operations[8].get()))); 493 ASSERT_TRUE(CheckPattern(33, 2, 2, *(operations[8].get()))); 494 495 ASSERT_TRUE(CheckPattern(37, 0, 2, *(operations[9].get()))); 496 497 END_TEST; 498} 499 500bool OobLimitsTest() { 501 BEGIN_TEST; 502 503 size_t op_size; 504 fbl::unique_ptr<NandDevice> device = CreateDevice(&op_size); 505 ASSERT_TRUE(device); 506 507 NandTest test; 508 Operation operation(op_size, &test); 509 510 nand_op_t* op = operation.GetOperation(); 511 op->rw.command = NAND_OP_READ; 512 op->completion_cb = &NandTest::CompletionCb; 513 514 device->Queue(op); 515 ASSERT_TRUE(test.Wait()); 516 ASSERT_EQ(ZX_ERR_OUT_OF_RANGE, operation.status()); 517 518 op->rw.length = 1; 519 device->Queue(op); 520 ASSERT_TRUE(test.Wait()); 521 ASSERT_EQ(ZX_ERR_BAD_HANDLE, operation.status()); 522 523 op->rw.offset_nand = kNumPages; 524 device->Queue(op); 525 ASSERT_TRUE(test.Wait()); 526 ASSERT_EQ(ZX_ERR_OUT_OF_RANGE, operation.status()); 527 528 ASSERT_TRUE(operation.SetOobVmo()); 529 530 op->rw.offset_nand = kNumPages - 1; 531 device->Queue(op); 532 ASSERT_TRUE(test.Wait()); 533 ASSERT_EQ(ZX_OK, operation.status()); 534 535 op->rw.length = 5; 536 device->Queue(op); 537 ASSERT_TRUE(test.Wait()); 538 ASSERT_EQ(ZX_ERR_OUT_OF_RANGE, operation.status()); 539 540 END_TEST; 541} 542 543bool ReadWriteOobTest() { 544 BEGIN_TEST; 545 546 size_t op_size; 547 fbl::unique_ptr<NandDevice> device = CreateDevice(&op_size); 548 ASSERT_TRUE(device); 549 550 NandTest test; 551 Operation operation(op_size, &test); 552 ASSERT_TRUE(operation.SetOobVmo()); 553 554 const char desired[kOobSize] = { 'a', 'b', 'c', 'd' }; 555 memcpy(operation.buffer(), desired, kOobSize); 556 557 nand_op_t* op = operation.GetOperation(); 558 op->rw.corrected_bit_flips = 125; 559 560 SetForWrite(2, 1, &operation); 561 device->Queue(op); 562 563 ASSERT_TRUE(test.Wait()); 564 ASSERT_EQ(ZX_OK, operation.status()); 565 ASSERT_EQ(125, op->rw.corrected_bit_flips); // Doesn't modify the value. 566 567 op->rw.command = NAND_OP_READ; 568 op->rw.length = 2; 569 op->rw.offset_nand = 1; 570 memset(operation.buffer(), 0, kOobSize * 2); 571 572 device->Queue(op); 573 ASSERT_TRUE(test.Wait()); 574 ASSERT_EQ(ZX_OK, operation.status()); 575 ASSERT_EQ(0, op->rw.corrected_bit_flips); 576 577 // The "second page" has the data of interest. 578 ASSERT_EQ(0, memcmp(operation.buffer() + kOobSize, desired, kOobSize)); 579 580 END_TEST; 581} 582 583bool ReadWriteDataAndOobTest() { 584 BEGIN_TEST; 585 586 size_t op_size; 587 fbl::unique_ptr<NandDevice> device = CreateDevice(&op_size); 588 ASSERT_TRUE(device); 589 590 NandTest test; 591 Operation operation(op_size, &test); 592 ASSERT_TRUE(operation.SetDataVmo()); 593 ASSERT_TRUE(operation.SetOobVmo()); 594 595 memset(operation.buffer(), 0x55, kPageSize * 2); 596 memset(operation.buffer() + kPageSize * 2, 0xaa, kOobSize * 2); 597 598 nand_op_t* op = operation.GetOperation(); 599 op->rw.corrected_bit_flips = 125; 600 601 SetForWrite(2, 2, &operation); 602 op->rw.offset_oob_vmo = 2; // OOB is right after data. 603 device->Queue(op); 604 605 ASSERT_TRUE(test.Wait()); 606 ASSERT_EQ(ZX_OK, operation.status()); 607 ASSERT_EQ(125, op->rw.corrected_bit_flips); // Doesn't modify the value. 608 609 op->rw.command = NAND_OP_READ; 610 memset(operation.buffer(), 0, kPageSize * 4); 611 612 device->Queue(op); 613 ASSERT_TRUE(test.Wait()); 614 ASSERT_EQ(ZX_OK, operation.status()); 615 ASSERT_EQ(0, op->rw.corrected_bit_flips); 616 617 // Verify data. 618 ASSERT_TRUE(CheckPattern(0x55, 0, 2, operation)); 619 620 // Verify OOB. 621 memset(operation.buffer(), 0xaa, kPageSize); 622 ASSERT_EQ(0, memcmp(operation.buffer() + kPageSize * 2, operation.buffer(), kOobSize * 2)); 623 624 END_TEST; 625} 626 627bool EraseLimitsTest() { 628 BEGIN_TEST; 629 630 size_t op_size; 631 fbl::unique_ptr<NandDevice> device = CreateDevice(&op_size); 632 ASSERT_TRUE(device); 633 634 NandTest test; 635 Operation operation(op_size, &test); 636 ASSERT_TRUE(operation.SetDataVmo()); 637 638 nand_op_t* op = operation.GetOperation(); 639 op->erase.command = NAND_OP_ERASE; 640 op->completion_cb = &NandTest::CompletionCb; 641 642 device->Queue(op); 643 ASSERT_TRUE(test.Wait()); 644 ASSERT_EQ(ZX_ERR_OUT_OF_RANGE, operation.status()); 645 646 op->erase.first_block = 5; 647 op->erase.num_blocks = 1; 648 device->Queue(op); 649 ASSERT_TRUE(test.Wait()); 650 ASSERT_EQ(ZX_ERR_OUT_OF_RANGE, operation.status()); 651 652 op->erase.first_block = 4; 653 op->erase.num_blocks = 2; 654 device->Queue(op); 655 ASSERT_TRUE(test.Wait()); 656 ASSERT_EQ(ZX_ERR_OUT_OF_RANGE, operation.status()); 657 658 END_TEST; 659} 660 661bool EraseTest() { 662 BEGIN_TEST; 663 664 size_t op_size; 665 fbl::unique_ptr<NandDevice> device = CreateDevice(&op_size); 666 ASSERT_TRUE(device); 667 668 NandTest test; 669 Operation operation(op_size, &test); 670 671 nand_op_t* op = operation.GetOperation(); 672 op->erase.command = NAND_OP_ERASE; 673 op->erase.first_block = 3; 674 op->erase.num_blocks = 2; 675 op->completion_cb = &NandTest::CompletionCb; 676 677 device->Queue(op); 678 ASSERT_TRUE(test.Wait()); 679 ASSERT_EQ(ZX_OK, operation.status()); 680 681 memset(op, 0, sizeof(*op)); 682 SetForRead(0, kNumPages, &operation); 683 ASSERT_TRUE(operation.SetDataVmo()); 684 ASSERT_TRUE(operation.SetOobVmo()); 685 op->rw.offset_oob_vmo = kNumPages; 686 device->Queue(op); 687 688 ASSERT_TRUE(test.Wait()); 689 ASSERT_EQ(ZX_OK, operation.status()); 690 ASSERT_TRUE(CheckPattern(0xff, 0, kNumPages, operation)); 691 692 // Verify OOB area. 693 memset(operation.buffer(), 0xff, kOobSize * kNumPages); 694 ASSERT_EQ(0, 695 memcmp(operation.buffer() + kPageSize * kNumPages, operation.buffer(), 696 kOobSize * kNumPages)); 697 698 END_TEST; 699} 700 701} // namespace 702 703BEGIN_TEST_CASE(RamNandTests) 704RUN_TEST_SMALL(TrivialLifetimeTest) 705RUN_TEST_SMALL(DdkLifetimeTest) 706RUN_TEST_SMALL(BasicDeviceProtocolTest) 707RUN_TEST_SMALL(UnlinkTest) 708RUN_TEST_SMALL(QueryTest) 709RUN_TEST_SMALL(FactoryBadBlockListTest) 710RUN_TEST_SMALL(QueueOneTest) 711RUN_TEST_SMALL(ReadWriteTest) 712RUN_TEST_SMALL(QueueMultipleTest) 713RUN_TEST_SMALL(OobLimitsTest) 714RUN_TEST_SMALL(ReadWriteOobTest) 715RUN_TEST_SMALL(ReadWriteDataAndOobTest) 716RUN_TEST_SMALL(EraseLimitsTest) 717RUN_TEST_SMALL(EraseTest) 718END_TEST_CASE(RamNandTests) 719