# 近来做 Stanford CS140e 的一些进展和思考（5）

在[上一篇文章](https://jia.je/programming/2018/02/27/thoughts-on-stanford-cs140e-4/index.md)之后，作者多次延期跳票之后（again），终于放出了 `Assignment 2 Phase 3: Saddle Up` 。这次，我们要做的变成了把已经写好的（错漏百出）的 `fat32` 的驱动搬到树莓派里面去，然后实现一些基本的 `shell` 命令： `ls` `cat` `cd` 等等。作者首先更新了老版本的新的测试样例，放了一些映像然后提供了预期的结果，结果发现，这里的 `fat32` 有一些不同，主要的就是 `bytes_per_sector` 不是 `512` 了，意味着物理的扇区和逻辑扇区并不一致。同时， `sectors_per_cluster` 也不是 `1` 了，需要考虑多个扇区的情况。同时， `read_cluster` 传入的 `offset` 也可能不再是第一个 `sector` 中的，所以需要做一个处理。对于物理和逻辑扇区的问题，作者推荐的方案是，把 `fat32` 之外的扇区保持不变，把其内的扇区视为逻辑扇区。这样，其它代码都可以透明地工作，而不用到处更改，这就体现了封装的威力。接着，作者提供了一个写好了的 `libsd` 和一些导出的函数，使用这些函数即可。不过，在错误处理和 `timeout` 上也遇到了一些坑。后面，把东西搬到树莓派上运行，问题就出现了：读取了第一个扇区（即 `MBR` 所在的扇区）之后，直接就死掉了。想了半天都没找到方案，突然想起可以利用 `panic!` 对错误语句进行二分查找。查找了大概有七八个小时之后，终于发现，问题出现在读取一个 `u32` 类型的变量上。我起初怀疑是栈出了问题，所以放到堆上分配，然而还是不行。忽然想起以前遇到的对齐问题，在 `AArch64` 架构上，可能为了简化，读取的 `u32` 必须对齐到四个字节上。于是找了找 `Rust` 中的对齐方面的文档，找到了 `#[repr(align=4)]` 这种表示方法，代替了原来的 `#[repr(packed)]` ，并且把数据先拷贝到对齐后的栈上的对应数据结构，然后再读取对应的项。果然，这个问题就解决了。然后又发现我的盘中会出现 `lfn` 项并不是从后往前的情况，于是我又修改了一下相关的代码。现在，终于可以成功地 `ls` `cat` `cd` 。

不过还是要吐槽一下，作者的测试用的映像文件中，会出现 `0xE5` 表示这个项已经被删除的情况，但是似乎作者的代码并没有处理这个，所以在预期的输出中出现了一些明显不正确的结果，导致我的代码跑测试并不能通过。而且，作者的代码在一些情况下会把文件的后缀漏掉。作者后来更新了几次测试的文件，不过这个问题只解决了一部分，并没有完全解决。坐等作者继续放出新的测试文件吧。

更新：[下一篇在这里](https://jia.je/programming/2018/03/05/thoughts-on-stanford-cs140e-6/index.md)。
