103 lines
2.8 KiB
C
103 lines
2.8 KiB
C
// POSIX fd-layer regression for GNO (punch-list #9): exercise the GS/OS-toolbox
|
|
// emulation of creat/write/close/open/read/lseek/unlink over the gsos* wrappers.
|
|
// Round-trips a fixed 16-byte payload through a real GS/OS file in the login cwd
|
|
// (/home/root) and asserts every stage via bank-2 absolute markers (DBR-
|
|
// independent), per the gnoHeapProbe/gnoForkWaitProbe convention.
|
|
//
|
|
// 0x025000 C0DE reached end (no hang in the fd layer)
|
|
// 0x025002 0001 read-back payload matched what was written
|
|
// 0x025004 0001 creat() returned a real GS/OS refNum (>= 4)
|
|
// 0x025006 0001 write() wrote all 16 bytes
|
|
// 0x025008 0001 read() read all 16 bytes back
|
|
// 0x02500A 0001 open(O_RDONLY) returned a real refNum (>= 4)
|
|
// 0x02500C 0001 lseek(SEEK_SET,4) + 1-byte read landed on payload[4]
|
|
// 0x02500E 0001 unlink() removed the file
|
|
#include <stdint.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#define M(a) (*(volatile uint16_t *)(a))
|
|
|
|
static const char kPath[] = "fdprobe.tmp";
|
|
static const uint8_t kData[16] = {
|
|
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
|
0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50
|
|
};
|
|
|
|
|
|
int main(void) {
|
|
uint8_t rbuf[16];
|
|
uint16_t ok;
|
|
int fd;
|
|
long n;
|
|
long pos;
|
|
char one;
|
|
uint8_t i;
|
|
|
|
M(0x025000UL) = 0x0000;
|
|
M(0x025002UL) = 0xDEAD;
|
|
M(0x025004UL) = 0xDEAD;
|
|
M(0x025006UL) = 0xDEAD;
|
|
M(0x025008UL) = 0xDEAD;
|
|
M(0x02500AUL) = 0xDEAD;
|
|
M(0x02500CUL) = 0xDEAD;
|
|
M(0x02500EUL) = 0xDEAD;
|
|
ok = 1;
|
|
|
|
// Create + write the payload.
|
|
fd = creat(kPath, 0);
|
|
if (fd >= 4) {
|
|
M(0x025004UL) = 0x0001;
|
|
n = write(fd, kData, 16);
|
|
if (n == 16) {
|
|
M(0x025006UL) = 0x0001;
|
|
} else {
|
|
ok = 0;
|
|
}
|
|
close(fd);
|
|
} else {
|
|
ok = 0;
|
|
}
|
|
|
|
// Reopen read-only and read the payload back.
|
|
fd = open(kPath, O_RDONLY);
|
|
if (fd >= 4) {
|
|
M(0x02500AUL) = 0x0001;
|
|
n = read(fd, rbuf, 16);
|
|
if (n == 16) {
|
|
M(0x025008UL) = 0x0001;
|
|
} else {
|
|
ok = 0;
|
|
}
|
|
for (i = 0; i < 16; i++) {
|
|
if (rbuf[i] != kData[i]) {
|
|
ok = 0;
|
|
}
|
|
}
|
|
// Seek back into the file and confirm the byte at offset 4.
|
|
pos = lseek(fd, 4, SEEK_SET);
|
|
one = 0;
|
|
read(fd, &one, 1);
|
|
if (pos == 4 && (uint8_t)one == kData[4]) {
|
|
M(0x02500CUL) = 0x0001;
|
|
} else {
|
|
ok = 0;
|
|
}
|
|
close(fd);
|
|
} else {
|
|
ok = 0;
|
|
}
|
|
|
|
// Remove the file.
|
|
if (unlink(kPath) == 0) {
|
|
M(0x02500EUL) = 0x0001;
|
|
} else {
|
|
ok = 0;
|
|
}
|
|
|
|
M(0x025002UL) = ok ? 0x0001 : 0xDEAD;
|
|
M(0x025000UL) = 0xC0DE;
|
|
for (volatile unsigned long j = 0; j < 600000UL; j++) {
|
|
}
|
|
return 0;
|
|
}
|