/* Copyright (C) 2005 David Decotigny This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "fstest_utils.h" /** * @file chartest.c * * Character devices tests */ int main(void) { int fd, len; unsigned int sum, mem_size; char buff[256]; char *uaddr; bochs_printf("Hi from chartest\n"); bochs_printf("WARNING: This test will eventually write 0 on kernel code !\n"); bochs_printf("This WILL crash the kernel (as expected...) !\n"); printf("WARNING: This test will eventually write 0 on kernel code !\n"); printf("This WILL crash the kernel (as expected...) !\n"); /* Make things more complicated */ fork(); fork(); /* * /dev/zero */ TEST_EXPECT_CONDITION(fd = open("/dev/zero", O_RDWR), RETVAL == 3); /* Make things more complicated: spawn and stay in child */ if (fork() > 0) return 0; strzcpy(buff, "Garbage", sizeof(buff)); TEST_EXPECT_CONDITION(len = read(fd, buff, sizeof(buff)), RETVAL == sizeof(buff)); /* Make sure it is full with 0 */ for (len = 0 ; len < sizeof(buff) ; len ++) if (buff[len]) break; TEST_EXPECT_CONDITION(len, RETVAL == sizeof(buff)); TEST_EXPECT_CONDITION(len = write(fd, 0, 123456789), RETVAL == 123456789); TEST_EXPECT_CONDITION(len = lseek(fd, 1234, SEEK_SET), RETVAL == 1234); /* Map it once */ TEST_EXPECT_CONDITION(uaddr = mmap(NULL, 8192, PROT_READ | PROT_WRITE, 0, fd, 4096), RETVAL != (int)NULL); /* Make sure it is full with 0 */ for (len = 0 ; len < 8192 ; len ++) if (uaddr[len]) break; TEST_EXPECT_CONDITION(len, RETVAL == 8192); strzcpy(uaddr, "Hello /dev/zero", 8192); TEST_EXPECT_CONDITION(strcmp(uaddr, "Hello /dev/zero"), RETVAL == 0); /* Map it again */ TEST_EXPECT_CONDITION(uaddr = mmap(NULL, 8192, PROT_READ | PROT_WRITE, 0, fd, 4096), RETVAL != (int)NULL); /* Make sure it is full with 0 */ for (len = 0 ; len < 8192 ; len ++) if (uaddr[len]) break; TEST_EXPECT_CONDITION(len, RETVAL == 8192); strzcpy(uaddr, "Hello /dev/zero", 8192); TEST_EXPECT_CONDITION(strcmp(uaddr, "Hello /dev/zero"), RETVAL == 0); TEST_EXPECT_CONDITION(close(fd), RETVAL == 0); /* * /dev/null */ TEST_EXPECT_CONDITION(fd = open("/dev/null", O_RDWR), RETVAL == 3); /* Make things more complicated: spawn and stay in child */ if (fork() > 0) return 0; strzcpy(buff, "Garbage", sizeof(buff)); TEST_EXPECT_CONDITION(len = read(fd, buff, sizeof(buff)), RETVAL == 0); /* Make sure buffer did not change */ TEST_EXPECT_CONDITION(strcmp("Garbage", buff), RETVAL == 0); TEST_EXPECT_CONDITION(len = write(fd, 0, 123456789), RETVAL == 123456789); TEST_EXPECT_CONDITION(len = lseek(fd, 1234, SEEK_SET), RETVAL == 1234); /* Map it once */ TEST_EXPECT_CONDITION(uaddr = mmap(NULL, 8192, PROT_READ | PROT_WRITE, 0, fd, 4096), RETVAL != (int)NULL); /* Make sure it is full with 0 */ for (len = 0 ; len < 8192 ; len ++) if (uaddr[len]) break; TEST_EXPECT_CONDITION(len, RETVAL == 8192); strzcpy(uaddr, "Hello /dev/null", 8192); TEST_EXPECT_CONDITION(strcmp(uaddr, "Hello /dev/null"), RETVAL == 0); /* Map it again */ TEST_EXPECT_CONDITION(uaddr = mmap(NULL, 8192, PROT_READ | PROT_WRITE, 0, fd, 4096), RETVAL != (int)NULL); /* Make sure it is full with 0 */ for (len = 0 ; len < 8192 ; len ++) if (uaddr[len]) break; TEST_EXPECT_CONDITION(len, RETVAL == 8192); strzcpy(uaddr, "Hello /dev/null", 8192); TEST_EXPECT_CONDITION(strcmp(uaddr, "Hello /dev/null"), RETVAL == 0); TEST_EXPECT_CONDITION(close(fd), RETVAL == 0); /* * Invalid device instance of zero.c */ TEST_EXPECT_CONDITION(mknod("/dev/invalid_zero", S_IRUSR | S_IWUSR, S_IFCHR, 1, 42), RETVAL == 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(fd = open("/dev/invalid_zero", O_RDWR), RETVAL < 0); TEST_EXPECT_CONDITION(unlink("/dev/invalid_zero"), RETVAL == 0); /* * Invalid device class / device instance */ TEST_EXPECT_CONDITION(mknod("/dev/invalid_devclass", S_IRUSR | S_IWUSR, S_IFCHR, 54654, 476576), RETVAL == 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(fd = open("/dev/invalid_devclass", O_RDWR), RETVAL < 0); TEST_EXPECT_CONDITION(unlink("/dev/invalid_devclass"), RETVAL == 0); /* * Make a checksum of all physical memory (/dev/mem) */ TEST_EXPECT_CONDITION(fd = open("/dev/mem", O_RDONLY), RETVAL == 3); /* Make things more complicated: spawn and stay in child */ if (fork() > 0) return 0; for (mem_size = 0, sum = 0 ; len = read(fd, buff, sizeof(buff)), len > 0 ; mem_size += len) { char *c; if (((mem_size / sizeof(buff)) % 4000) == 0) printf("Read %d MB of physical memory\n", mem_size >> 20); for (c = buff ; c - buff < len ; c++) sum += *c; } TEST_EXPECT_CONDITION(mem_size, RETVAL > 0); printf("Checkum of RAM (%d MB) is %x\n", mem_size >> 20, sum); TEST_EXPECT_CONDITION(len = lseek(fd, 0, SEEK_SET), len == 0); TEST_EXPECT_CONDITION(len = lseek(fd, 0, SEEK_END), len == mem_size); TEST_EXPECT_CONDITION(close(fd), RETVAL == 0); /* * Make a checksum of main kernel memory (/dev/kmem) */ TEST_EXPECT_CONDITION(fd = open("/dev/kmem", O_RDONLY), RETVAL == 3); /* Make things more complicated: spawn and stay in child */ if (fork() > 0) return 0; /* Seek to beginning of main .text section */ TEST_EXPECT_CONDITION(lseek(fd, 0x201000, SEEK_SET), RETVAL == 0x201000); for (mem_size = 0, sum = 0 ; len = read(fd, buff, sizeof(buff)), len > 0 ; mem_size += len) { char *c; if (((mem_size / sizeof(buff)) % 400) == 0) printf("Read %d kB of kernel memory\n", mem_size >> 10); for (c = buff ; c - buff < len ; c++) sum += *c; } TEST_EXPECT_CONDITION(mem_size, RETVAL > 0); printf("Checkum of main kernel area (%d kB) is %x\n", mem_size >> 10, sum); TEST_EXPECT_CONDITION(len = lseek(fd, 0, SEEK_SET), len == 0); TEST_EXPECT_CONDITION(len = lseek(fd, 0, SEEK_END), len == 0x40000000); TEST_EXPECT_CONDITION(close(fd), RETVAL == 0); printf("Bye from chartest\n"); ls("/", 1, 1); /* Crash the whole kernel */ bochs_printf("NOW Crashing the whole thing !...\n"); { int i; for (i = 5 ; i >= 0 ; i --) { printf("Crashing the whole thing in %ds !... \r", i); sleep(1); } } printf("\nGO !\n"); TEST_EXPECT_CONDITION(fd = open("/dev/mem", O_WRONLY), RETVAL == 3); memset(buff, 0xcc, sizeof(buff)); while (write(fd, buff, sizeof(buff))) continue; return 0; }