/* YOUR FILE-HEADER COMMENT HERE */ /* * This file uses kernel-doc style comments, which is similar to * Javadoc and Doxygen-style comments. See * ~/linux/Documentation/kernel-doc-nano-HOWTO.txt for details. */ /* * Getting compilation warnings? The Linux kernel is written against * C89, which means: * - No // comments, and * - All variables must be declared at the top of functions. * Read ~/linux/Documentation/CodingStyle to ensure your project * compiles without warnings. */ #define pr_fmt(fmt) "MM: " fmt #include #include #include #include #include #include #include #include #define NUM_PEGS 4 #define NUM_COLORS 6 /** true if user is in the middle of a game */ static bool game_active; /** code that player is trying to guess */ static int target_code[NUM_PEGS]; /** tracks number of guesses user has made */ static unsigned num_guesses; /** current status of the game */ static char game_status[80]; /** buffer that logs guesses for the current game */ static char *user_view; /** * mm_read() - callback invoked when a process reads from * /dev/mm * @filp: process's file object that is reading from this device (ignored) * @ubuf: destination buffer to store output * @count: number of bytes in @ubuf * @ppos: file offset (in/out parameter) * * Write to @ubuf the current status of the game, offset by * @ppos. Copy the lesser of @count and (string length of @game_status * - *@ppos). Then increment the value pointed to by @ppos by the * number of bytes copied. If @ppos is greater than or equal to the * length of @game_status, then copy nothing. * * Return: number of bytes written to @ubuf, or negative on error */ static ssize_t mm_read(struct file *filp, char __user * ubuf, size_t count, loff_t * ppos) { /* FIXME */ return -EPERM; } /** * mm_write() - callback invoked when a process writes to /dev/mm * @filp: process's file object that is reading from this device (ignored) * @ubuf: source buffer from user * @count: number of bytes in @ubuf * @ppos: file offset (ignored) * * If the user is not currently playing a game, then return -EINVAL. * * If @count is less than NUM_PEGS, then return -EINVAL. Otherwise, * interpret the first NUM_PEGS characters in @ubuf as the user's * guess. For each guessed peg, calculate how many are in the correct * value and position, and how many are simply the correct value. Then * update @num_guesses, @game_status, and @user_view. * * Caution: @ubuf is NOT a string; it is not necessarily * null-terminated. You CANNOT use strcpy() or strlen() on it! * * Return: @count, or negative on error */ static ssize_t mm_write(struct file *filp, const char __user * ubuf, size_t count, loff_t * ppos) { /* FIXME */ return -EPERM; } /** * mm_mmap() - callback invoked when a process mmap()s to /dev/mm * @filp: process's file object that is mapping to this device (ignored) * @vma: virtual memory allocation object containing mmap() request * * Create a read-only mapping from kernel memory (specifically, * @user_view) into user space. * * Code based upon * http://bloggar.combitech.se/ldc/2015/01/21/mmap-memory-between-kernel-and-userspace/ * * You do not need to modify this function. * * Return: 0 on success, negative on error. */ static int mm_mmap(struct file *filp, struct vm_area_struct *vma) { unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start); unsigned long page = vmalloc_to_pfn(user_view); if (size > PAGE_SIZE) return -EIO; vma->vm_pgoff = 0; vma->vm_page_prot = PAGE_READONLY; if (remap_pfn_range(vma, vma->vm_start, page, size, vma->vm_page_prot)) return -EAGAIN; return 0; } /** * mm_ctl_write() - callback invoked when a process writes to * /dev/mm_ctl * @filp: process's file object that is writing to this device (ignored) * @ubuf: source buffer from user * @count: number of bytes in @ubuf * @ppos: file offset (ignored) * * Copy the contents of @ubuf, up to the lesser of @count and 8 bytes, * to a temporary location. Then parse that character array as * following: * * start - Start a new game. If a game was already in progress, restart it. * quit - Quit the current game. If no game was in progress, do nothing. * * If the input is none of the above, then return -EINVAL. * * Caution: @ubuf is NOT a string; it is not necessarily * null-terminated. You CANNOT use strcpy() or strlen() on it! * * Return: @count, or negative on error */ static ssize_t mm_ctl_write(struct file *filp, const char __user * ubuf, size_t count, loff_t * ppos) { /* FIXME */ return -EPERM; } /** * mastermind_init() - entry point into the Mastermind kernel module * Return: 0 on successful initialization, negative on error */ static int __init mastermind_init(void) { pr_info("Initializing the game.\n"); user_view = vmalloc(PAGE_SIZE); if (!user_view) { pr_err("Could not allocate memory\n"); return -ENOMEM; } /* YOUR CODE HERE */ return 0; } /** * mastermind_exit() - called by kernel to clean up resources */ static void __exit mastermind_exit(void) { pr_info("Freeing resources.\n"); vfree(user_view); /* YOUR CODE HERE */ } module_init(mastermind_init); module_exit(mastermind_exit); MODULE_DESCRIPTION("CS421 Mastermind Game"); MODULE_LICENSE("GPL");