|
40 | 40 | #include "supervisor/memory.h"
|
41 | 41 | #include "supervisor/shared/rgb_led_status.h"
|
42 | 42 |
|
43 |
| -#define SPI_FLASH_PART1_START_BLOCK (0x1) |
44 |
| - |
45 | 43 | #define NO_SECTOR_LOADED 0xFFFFFFFF
|
46 | 44 |
|
47 | 45 | // The currently cached sector in the cache, ram or flash based.
|
@@ -268,7 +266,7 @@ uint32_t supervisor_flash_get_block_size(void) {
|
268 | 266 | uint32_t supervisor_flash_get_block_count(void) {
|
269 | 267 | // We subtract one erase sector size because we may use it as a staging area
|
270 | 268 | // for writes.
|
271 |
| - return SPI_FLASH_PART1_START_BLOCK + (flash_device->total_size - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE; |
| 269 | + return (flash_device->total_size - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE; |
272 | 270 | }
|
273 | 271 |
|
274 | 272 | // Flush the cache that was written to the scratch portion of flash. Only used
|
@@ -444,155 +442,88 @@ void supervisor_flash_flush(void) {
|
444 | 442 | spi_flash_flush_keep_cache(false);
|
445 | 443 | }
|
446 | 444 |
|
447 |
| -// Builds a partition entry for the MBR. |
448 |
| -static void build_partition(uint8_t *buf, int boot, int type, |
449 |
| - uint32_t start_block, uint32_t num_blocks) { |
450 |
| - buf[0] = boot; |
451 |
| - |
452 |
| - if (num_blocks == 0) { |
453 |
| - buf[1] = 0; |
454 |
| - buf[2] = 0; |
455 |
| - buf[3] = 0; |
456 |
| - } else { |
457 |
| - buf[1] = 0xff; |
458 |
| - buf[2] = 0xff; |
459 |
| - buf[3] = 0xff; |
460 |
| - } |
461 |
| - |
462 |
| - buf[4] = type; |
463 |
| - |
464 |
| - if (num_blocks == 0) { |
465 |
| - buf[5] = 0; |
466 |
| - buf[6] = 0; |
467 |
| - buf[7] = 0; |
468 |
| - } else { |
469 |
| - buf[5] = 0xff; |
470 |
| - buf[6] = 0xff; |
471 |
| - buf[7] = 0xff; |
472 |
| - } |
473 |
| - |
474 |
| - buf[8] = start_block; |
475 |
| - buf[9] = start_block >> 8; |
476 |
| - buf[10] = start_block >> 16; |
477 |
| - buf[11] = start_block >> 24; |
478 |
| - |
479 |
| - buf[12] = num_blocks; |
480 |
| - buf[13] = num_blocks >> 8; |
481 |
| - buf[14] = num_blocks >> 16; |
482 |
| - buf[15] = num_blocks >> 24; |
483 |
| -} |
484 |
| - |
485 | 445 | static int32_t convert_block_to_flash_addr(uint32_t block) {
|
486 |
| - if (SPI_FLASH_PART1_START_BLOCK <= block && block < supervisor_flash_get_block_count()) { |
| 446 | + if (0 <= block && block < supervisor_flash_get_block_count()) { |
487 | 447 | // a block in partition 1
|
488 |
| - block -= SPI_FLASH_PART1_START_BLOCK; |
489 | 448 | return block * FILESYSTEM_BLOCK_SIZE;
|
490 | 449 | }
|
491 | 450 | // bad block
|
492 | 451 | return -1;
|
493 | 452 | }
|
494 | 453 |
|
495 | 454 | bool external_flash_read_block(uint8_t *dest, uint32_t block) {
|
496 |
| - if (block == 0) { |
497 |
| - // Fake the MBR so we can decide on our own partition table |
498 |
| - for (int i = 0; i < 446; i++) { |
499 |
| - dest[i] = 0; |
500 |
| - } |
501 |
| - |
502 |
| - build_partition(dest + 446, 0, 0x01 /* FAT12 */, |
503 |
| - SPI_FLASH_PART1_START_BLOCK, |
504 |
| - supervisor_flash_get_block_count() - SPI_FLASH_PART1_START_BLOCK); |
505 |
| - build_partition(dest + 462, 0, 0, 0, 0); |
506 |
| - build_partition(dest + 478, 0, 0, 0, 0); |
507 |
| - build_partition(dest + 494, 0, 0, 0, 0); |
508 |
| - |
509 |
| - dest[510] = 0x55; |
510 |
| - dest[511] = 0xaa; |
511 |
| - |
512 |
| - return true; |
513 |
| - } else if (block < SPI_FLASH_PART1_START_BLOCK) { |
514 |
| - memset(dest, 0, FILESYSTEM_BLOCK_SIZE); |
515 |
| - return true; |
516 |
| - } else { |
517 |
| - // Non-MBR block, get data from flash memory. |
518 |
| - int32_t address = convert_block_to_flash_addr(block); |
519 |
| - if (address == -1) { |
520 |
| - // bad block number |
521 |
| - return false; |
522 |
| - } |
523 |
| - |
524 |
| - // Mask out the lower bits that designate the address within the sector. |
525 |
| - uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); |
526 |
| - uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); |
527 |
| - uint8_t mask = 1 << (block_index); |
528 |
| - // We're reading from the currently cached sector. |
529 |
| - if (current_sector == this_sector && (mask & dirty_mask) > 0) { |
530 |
| - if (MP_STATE_VM(flash_ram_cache) != NULL) { |
531 |
| - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; |
532 |
| - for (int i = 0; i < pages_per_block; i++) { |
533 |
| - memcpy(dest + i * SPI_FLASH_PAGE_SIZE, |
534 |
| - MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], |
535 |
| - SPI_FLASH_PAGE_SIZE); |
536 |
| - } |
537 |
| - return true; |
538 |
| - } else { |
539 |
| - uint32_t scratch_address = flash_device->total_size - SPI_FLASH_ERASE_SIZE + block_index * FILESYSTEM_BLOCK_SIZE; |
540 |
| - return read_flash(scratch_address, dest, FILESYSTEM_BLOCK_SIZE); |
541 |
| - } |
542 |
| - } |
543 |
| - return read_flash(address, dest, FILESYSTEM_BLOCK_SIZE); |
| 455 | + int32_t address = convert_block_to_flash_addr(block); |
| 456 | + if (address == -1) { |
| 457 | + // bad block number |
| 458 | + return false; |
544 | 459 | }
|
545 |
| -} |
546 | 460 |
|
547 |
| -bool external_flash_write_block(const uint8_t *data, uint32_t block) { |
548 |
| - if (block < SPI_FLASH_PART1_START_BLOCK) { |
549 |
| - // Fake writing below the flash partition. |
550 |
| - return true; |
551 |
| - } else { |
552 |
| - // Non-MBR block, copy to cache |
553 |
| - int32_t address = convert_block_to_flash_addr(block); |
554 |
| - if (address == -1) { |
555 |
| - // bad block number |
556 |
| - return false; |
557 |
| - } |
558 |
| - // Wait for any previous writes to finish. |
559 |
| - wait_for_flash_ready(); |
560 |
| - // Mask out the lower bits that designate the address within the sector. |
561 |
| - uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); |
562 |
| - uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); |
563 |
| - uint8_t mask = 1 << (block_index); |
564 |
| - // Flush the cache if we're moving onto a sector or we're writing the |
565 |
| - // same block again. |
566 |
| - if (current_sector != this_sector || (mask & dirty_mask) > 0) { |
567 |
| - // Check to see if we'd write to an erased page. In that case we |
568 |
| - // can write directly. |
569 |
| - if (page_erased(address)) { |
570 |
| - return write_flash(address, data, FILESYSTEM_BLOCK_SIZE); |
571 |
| - } |
572 |
| - if (current_sector != NO_SECTOR_LOADED) { |
573 |
| - spi_flash_flush_keep_cache(true); |
574 |
| - } |
575 |
| - if (MP_STATE_VM(flash_ram_cache) == NULL && !allocate_ram_cache()) { |
576 |
| - erase_sector(flash_device->total_size - SPI_FLASH_ERASE_SIZE); |
577 |
| - wait_for_flash_ready(); |
578 |
| - } |
579 |
| - current_sector = this_sector; |
580 |
| - dirty_mask = 0; |
581 |
| - } |
582 |
| - dirty_mask |= mask; |
583 |
| - // Copy the block to the appropriate cache. |
| 461 | + // Mask out the lower bits that designate the address within the sector. |
| 462 | + uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); |
| 463 | + uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); |
| 464 | + uint8_t mask = 1 << (block_index); |
| 465 | + // We're reading from the currently cached sector. |
| 466 | + if (current_sector == this_sector && (mask & dirty_mask) > 0) { |
584 | 467 | if (MP_STATE_VM(flash_ram_cache) != NULL) {
|
585 | 468 | uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE;
|
586 | 469 | for (int i = 0; i < pages_per_block; i++) {
|
587 |
| - memcpy(MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], |
588 |
| - data + i * SPI_FLASH_PAGE_SIZE, |
| 470 | + memcpy(dest + i * SPI_FLASH_PAGE_SIZE, |
| 471 | + MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], |
589 | 472 | SPI_FLASH_PAGE_SIZE);
|
590 | 473 | }
|
591 | 474 | return true;
|
592 | 475 | } else {
|
593 | 476 | uint32_t scratch_address = flash_device->total_size - SPI_FLASH_ERASE_SIZE + block_index * FILESYSTEM_BLOCK_SIZE;
|
594 |
| - return write_flash(scratch_address, data, FILESYSTEM_BLOCK_SIZE); |
| 477 | + return read_flash(scratch_address, dest, FILESYSTEM_BLOCK_SIZE); |
| 478 | + } |
| 479 | + } |
| 480 | + return read_flash(address, dest, FILESYSTEM_BLOCK_SIZE); |
| 481 | +} |
| 482 | + |
| 483 | +bool external_flash_write_block(const uint8_t *data, uint32_t block) { |
| 484 | + // Non-MBR block, copy to cache |
| 485 | + int32_t address = convert_block_to_flash_addr(block); |
| 486 | + if (address == -1) { |
| 487 | + // bad block number |
| 488 | + return false; |
| 489 | + } |
| 490 | + // Wait for any previous writes to finish. |
| 491 | + wait_for_flash_ready(); |
| 492 | + // Mask out the lower bits that designate the address within the sector. |
| 493 | + uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); |
| 494 | + uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); |
| 495 | + uint8_t mask = 1 << (block_index); |
| 496 | + // Flush the cache if we're moving onto a sector or we're writing the |
| 497 | + // same block again. |
| 498 | + if (current_sector != this_sector || (mask & dirty_mask) > 0) { |
| 499 | + // Check to see if we'd write to an erased page. In that case we |
| 500 | + // can write directly. |
| 501 | + if (page_erased(address)) { |
| 502 | + return write_flash(address, data, FILESYSTEM_BLOCK_SIZE); |
| 503 | + } |
| 504 | + if (current_sector != NO_SECTOR_LOADED) { |
| 505 | + spi_flash_flush_keep_cache(true); |
| 506 | + } |
| 507 | + if (MP_STATE_VM(flash_ram_cache) == NULL && !allocate_ram_cache()) { |
| 508 | + erase_sector(flash_device->total_size - SPI_FLASH_ERASE_SIZE); |
| 509 | + wait_for_flash_ready(); |
595 | 510 | }
|
| 511 | + current_sector = this_sector; |
| 512 | + dirty_mask = 0; |
| 513 | + } |
| 514 | + dirty_mask |= mask; |
| 515 | + // Copy the block to the appropriate cache. |
| 516 | + if (MP_STATE_VM(flash_ram_cache) != NULL) { |
| 517 | + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; |
| 518 | + for (int i = 0; i < pages_per_block; i++) { |
| 519 | + memcpy(MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], |
| 520 | + data + i * SPI_FLASH_PAGE_SIZE, |
| 521 | + SPI_FLASH_PAGE_SIZE); |
| 522 | + } |
| 523 | + return true; |
| 524 | + } else { |
| 525 | + uint32_t scratch_address = flash_device->total_size - SPI_FLASH_ERASE_SIZE + block_index * FILESYSTEM_BLOCK_SIZE; |
| 526 | + return write_flash(scratch_address, data, FILESYSTEM_BLOCK_SIZE); |
596 | 527 | }
|
597 | 528 | }
|
598 | 529 |
|
|
0 commit comments