Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

#include <sys/types.h>
#include <sys/module.h>
#include <sys/systm.h>  /* uprintf */
#include <sys/param.h>  /* defines used in kernel.h */
#include <sys/kernel.h> /* types used in module initialization */
#include <sys/conf.h>   /* cdevsw struct */
#include <sys/uio.h>    /* uio struct */
#include <sys/sysctl.h>
#include <sys/malloc.h>
#include "lockdoc_internal.h"

/*
 * Big thanks to the authors of the FreeBSD architecture handbook.
 * This driver is based on the echo example.
 * https://www.freebsd.org/doc/en/books/arch-handbook/driverbasics-char.html
 */

/* Function prototypes */
static d_read_t      lockdoc_version_read;

static struct cdev *lockdoc_version_dev;


/* Character device entry points */
static struct cdevsw lockdoc_version_cdevsw = {
	.d_version = D_VERSION,
	.d_read = lockdoc_version_read,
	.d_name = "lockdoc_version",
};

static int
lockdoc_version_loader(struct module *m __unused, int what, void *arg __unused)
{
	int error = 0;

	switch (what) {
	case MOD_LOAD:                /* kldload */
		error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
		    &lockdoc_version_dev,
		    &lockdoc_version_cdevsw,
		    0,
		    UID_ROOT,
		    GID_WHEEL,
		    0400,
		    DEV_DIR_NAME "/version");
		if (error != 0) {
			break;
		}

		break;
	case MOD_UNLOAD:
		destroy_dev(lockdoc_version_dev);
		break;
	default:
		error = EOPNOTSUPP;
		break;
	}
	return (error);
}

#define BUFSIZE 70
static int lockdoc_version_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)
{
	size_t amt, len;
	int error;
	char *buffer;

	buffer = malloc(BUFSIZE, M_TEMP, M_WAITOK | M_ZERO);
	if (buffer == NULL) {
		return (ENOMEM);
	}
	len = snprintf(buffer, BUFSIZE, "%s\n", lockdoc_version);
	if (len >= BUFSIZE) {
		len = BUFSIZE;
	}
	/*
	 * How big is this read operation?  Either as big as the user wants,
	 * or as big as the remaining data.  Note that the 'len' does not
	 * include the trailing null character.
	 */
	amt = MIN(uio->uio_resid, uio->uio_offset >= len ? 0 :
	    len - uio->uio_offset);

	error = uiomove(buffer, amt, uio);
	if (error != 0) {
		uprintf("uiomove failed!\n");
	}
	free(buffer, M_TEMP);

	return (error);
}
#undef BUFSIZE

DEV_MODULE(lockdoc_version, lockdoc_version_loader, NULL);