├── Chapter_1_Introduction_to_Device_Drivers.md ├── Chapter_2_Building_and_Running_Modules.md ├── Chapter_3_Char_Drivers.md ├── Chapter_4_Debugging_Techniques.md ├── Chapter_5_Concurrency_and_Race.md ├── Chapter_6_Advanced_Char_Drivers.md ├── Chapter_7_Time_Delays_DeferedWork.md ├── Chapter_8_Allocating_Memory.md ├── Chapter_9_Communicating_with_Hardware.md ├── Chapter__10_Interrupt_Handling.md ├── Chapter__11_Data_Types.md ├── Chapter__12_PCI_Drivers.md ├── Chapter__13_USB_Drivers.md ├── Chapter__14_Device_Model.md ├── Chapter__15_Memory_Mapping_DMA.md ├── Chapter__16_Block_Drivers.md ├── Chapter__17_Network_Drivers.md ├── Chapter__18_TTY_Drivers.md ├── Code_Examples ├── Block_Driver │ ├── Makefile │ ├── README.md │ ├── domblockdev.c │ ├── fun_text │ └── sonnet ├── Char_Driver │ ├── Makefile │ ├── README.md │ └── main.c ├── Hello_World │ ├── Makefile │ ├── README.md │ └── hello.c ├── Net_Driver │ ├── Makefile │ ├── README.md │ └── filter.c ├── README.md ├── scull │ ├── Makefile │ ├── Module.symvers │ ├── README.md │ ├── access.c │ ├── access_ok_version.h │ ├── lddbus.h │ ├── main.c │ ├── modules.order │ ├── pipe.c │ ├── scull.h │ ├── scull.init │ ├── scull_load │ └── scull_unload ├── socketCAN │ ├── README.md │ ├── ReceiveRawPacket.c │ └── SendRawPacket.c └── tty │ ├── Makefile │ ├── README.md │ ├── tiny_serial.c │ └── tiny_tty.c └── README.md /Chapter_1_Introduction_to_Device_Drivers.md: -------------------------------------------------------------------------------- 1 | # LDD3 Chapter 1 Notes 2 | 3 | ## Brief Overview: 4 | This book consists of 18 chapters, each of which will be covered in this note set. The book covers up to linux kernel version 2.6.10, which was released 12/25/2004. This is really old, and the most recent version of the linux kernel as of January 2020 is the 5.4.13 kernel. Many important changes have been made over the years, and this note set will attempt to add in as much new detail as possible. 5 | 6 | The first part of the book moves from the software-oriented concepts to the hardware-related ones. This organization is meant to allow you to test the software on your own computer as far as possible without the need to plug external hardware into the machine. 7 | 8 | The second half of the book (chapters 12-18) describes block drivers and network interfaces and goes deeper into more advanced topics, such as working with the virtual memory subsystem and with the PCI and USB buses. Many developers do not need all of this material, but it is interesting as a view into how the Linux kernel works. 9 | 10 | ## Chapter 1. An Introduction to Device Drivers 11 | 12 | The Linux kernel is a large and complex body of code. People who desire to work with the kernel need an entry point where they can approach the code without being overwhelmed. Device drivers are one good place to start exploring. 13 | 14 | Device drivers are treated like distinct "black boxes" that make a piece of hardware respond to an internal programming interface. User activities are performed with a set of standardized calls that are independent of a specific driver. Mapping these calls to device-specific operations is the job of the driver. Drivers are made such that they can be built separately from the rest of the kernal and "plugged in" at runtime when needed. This modularity is supposed to make the drivers easy to write. 15 | 16 | This book attempts to explain drivers as generically as possible, without going into the specifics for one piece of hardware in too much detail. Many of the generic techniques can be applied to most drivers, though, which makes this book useful for setting up the general framework of any driver. 17 | 18 | This chapter does not introduce any code, but reviews important topics for future chapters. 19 | 20 | ### The distinction between Mechanism and Policy 21 | 22 | One of the best ideas behind Unix design, most programming problems can be split into two parts: 23 | 24 | 1. The mechanism - What capabilities are to be provided? 25 | 2. The policy - How those capabilities can be used? 26 | 27 | If these two issues are addressed by different parts of the program, or even different programs, the software package is easier to adapt and develop for particular needs. 28 | 29 | A programmer needs to pay attention to this distinction. Write kernel code to access hardware, but don't force policies on the user because different users have different needs. It should offer all the capability of the hardware without adding constraints. The trade-off then becomes a balance between adding as many possible options for the user and possible while keeping it simple so bugs and weird errors don't happen. 30 | 31 | Policy-free drivers have the following characteristics: 32 | 33 | 1. Support for both synchronous and asynchronous operation 34 | 2. The ability to be opened multiple times 35 | 3. The ability to use the full capabilities of the hardware 36 | 4. Lack of software layers to "simply things" 37 | 5. Tend to work better for end users 38 | 6. End up being easier to write and maintain 39 | 40 | Being policy-free is often a target for many designers. Many drivers are even released with user programs to help configure and connect to the target device. They can be simple command line utilities or fancy GUIs to help the user. The aim of this book is to cover the kernel, without much detail on the application programs or support library. 41 | 42 | In real life, you should always include configuration files that apply a default behavior to underlying mechanisms. 43 | 44 | ### Splitting the Kernel 45 | 46 | In a Unix-based system, several concurrent processes attend to different tasks. The kernel handles all of the requests that processes make for various system resources. The kernels role can be split into the following parts: 47 | 48 | 1. Process Management 49 | 2. Memory Management 50 | 3. Filesystems 51 | 4. Device Control 52 | 5. Networking 53 | 54 | #### 1. Process Management 55 | 56 | The kernel is in charge of creating, destroying, and connecting processes. It also schedules the CPU to be shared among many processes. 57 | 58 | #### 2. Memory Management 59 | 60 | The kernel builds up the virtual address space for each process. The different parts of the kernel interact with the memory-management subsystem through function calls such as malloc/free among many others. 61 | 62 | #### 3. Filesystems 63 | 64 | Almost everything in Unix can be treated as a file. The kernel builds a structured filesystem on top of of unstructured hardware. Linux also supports multiple file system types - all of which must be compatible with the kernel. 65 | 66 | #### 4. Device Control 67 | 68 | Device control operations are performed by code that is specific to the device being addressed. That code is called the device driver. Every peripheral on the system must have a driver for it embedded within the kernel. This part of the kernel operation is the focus of this book. 69 | 70 | #### Networking 71 | 72 | Most network operations are not specific to a process, and incoming packets are asynchronous events. The system is in charge of delivering packets across program and network interfaces, and must control the execution of programs according to their network activity. All routing and addressing issues also go through the kernel. 73 | 74 | ### Loadable Modules 75 | 76 | A piece of code that can be added to the kernel at runtime is called a module. There are many classes of modules, including device drivers. 77 | 78 | ### Classes of Devices 79 | 80 | There are three fundamental device types: 81 | 82 | 1. char module 83 | 2. block module 84 | 3. network module 85 | 86 | #### 1. Character Devices 87 | 88 | A device that can be accessed as a stream of bytes (like a file). A char driver is responsible for implementing this behavior. It usually implements open, close, read, and write system calls. The text console and serial ports are examples of char devices. Char devices are accessed by filesystem nodes, such as /dev/tty1 and dev/lp0. The difference between a char device and a regular file is that you can always move back and forth in a regular file, while most char devices are just data channels that can only be accessed sequentially. However, there are still some char devices that look like data areas and can be explored back and forth. 89 | 90 | #### 2. Block Devices 91 | 92 | A block device is a device that can host a filesystem. These are also accessed by filesystem nodes in the /dev directory. In Unix, they can usually only handle I/O operations that transfer one or more whole blocks, which may be 512 bytes in length. In Linux, they allow an application to read/write a block like a char device. This means that for Linux, char and block devices only differ in how they are managed internally by the kernel. They have completely different interface to the kernel than char drivers. 93 | 94 | #### 3. Network Interfaces 95 | 96 | Any network transaction is made through an interface. Functionally, one device is 97 | able to exchange data with other hosts. Usually, an interface is a hardware 98 | device, but it might also be a pure software device, e.g. the loopback interface. A network driver knows nothing about individual connections; it only handles the sending and receiving of packets. Since this is not stream oriented, a network interface cannot be easily mapped to a node in the filesystem. Instead of read/write functions like char and block drivers, the kernel calls special functions related to packet transmission. 99 | 100 | ### Security 101 | 102 | Any security check in the system is enforced by kernel code. Security is a policy issue that is often best handled at higher levels within the kernel under the control of the system administrator. There are some exceptions, though: 103 | 104 | - Avoid introducing security bugs 105 | - Input from a user process should be treated with great suspicion 106 | - Any memory obtained from the kernel should be zeroed or initialized before the user can access it 107 | - Avoid running unofficial kernels 108 | 109 | ### Linux Version Numbering 110 | 111 | Odd numbered kernels (2.7.x) are not stable. They are short lived development versions. 112 | Even numbered kernels (2.6.x) are stable and should be used for long-term development. 113 | This is no longer true! Linux 5.5 is stable, just like 5.4 and 5.3. Don't pay attention to the even/odd numbers anymore. 114 | 115 | -------------------------------------------------------------------------------- /Chapter_8_Allocating_Memory.md: -------------------------------------------------------------------------------- 1 | # LDD3 Chapter 8 Notes 2 | 3 | ## Chapter 8: Allocating Memory 4 | 5 | Chapter goal: learn the kernel set of memory primitives 6 | 7 | So far we have used kmalloc() and kfree() to allocate and free memory. The kernel offers much better memory management tools though, as this chapter will describe in more detail. 8 | 9 | ### The Real Story of kmalloc 10 | 11 | kmalloc is powerful and simple to use because of its similarity to malloc. It is fast and does not clear the memory it obtains. The allocated region is also contiguous in physical memory. Here are more details on kmalloc: 12 | 13 | The prototype for kmalloc is: 14 | 15 | ```c 16 | #include 17 | void *kmalloc(size_t size, int flags); 18 | ``` 19 | 20 | - The first argument is the size of the block to be allocated 21 | - The second argument controls to behavior of kmalloc in a number of different ways 22 | 23 | The most commonly used flag is `GFP_KERNEL` and it means that the calling function is executing a system call on behalf of a process. This means kmalloc can put the current process to sleep waiting for a page when called in low-memory situations. 24 | 25 | `GFP_KERNEL` is not always the best option, however, because sometimes kmalloc is called from outside a process’s context. This can happen with interrupt handlers, tasklets, and kernel timers. In this case we do not want to sleep the process and the driver should use a flag of `GFP_ATOMIC`. `GFP_ATOMIC` will use the last free page, and will fail if the allocation could not happen. 26 | 27 | There are symbols that represent frequently used combinations of flags. These are: 28 | 29 | ``` 30 | GFP_ATOMIC 31 | Used to allocate memory from interrupt handlers and other code outside of a 32 | process context. Never sleeps. 33 | 34 | GFP_KERNEL 35 | Normal allocation of kernel memory. May sleep. 36 | 37 | GFP_USER 38 | Used to allocate memory for user-space pages. It may sleep. 39 | 40 | GFP_HIGHUSER 41 | Like GFP_USER, but allocates from high memory, if any. High memory is 42 | described in the next subsection. 43 | 44 | GFP_NOIO 45 | GFP_NOFS 46 | These flags function like GFP_KERNEL, but they add restrictions on what the kernel 47 | can do to satisfy the request. A GFP_NOFS allocation is not allowed to perform any 48 | filesystem calls, while GFP_NOIO disallows the initiation of any I/O at all. 49 | They are used primarily in the filesystem and virtual memory code where an 50 | allocation may be allowed to sleep, but recursive filesystem calls would be a bad 51 | idea. 52 | ``` 53 | 54 | You can also use a boolean OR operator with any of the following flags: 55 | 56 | ``` 57 | __GFP_DMA 58 | This flag requests allocation to happen in the DMA-capable memory zone. The 59 | exact meaning is platform-dependent and is explained in the following section. 60 | 61 | __GFP_HIGHMEM 62 | This flag indicates that the allocated memory may be located in high memory. 63 | 64 | __GFP_COLD 65 | Normally, the memory allocator tries to return “cache warm” pages—pages that 66 | are likely to be found in the processor cache. Instead, this flag requests a 67 | “cold” page, which has not been used in some time. It is useful for allocating 68 | pages for DMA reads, where presence in the processor cache is not useful. 69 | 70 | __GFP_NOWARN 71 | This rarely used flag prevents the kernel from issuing warnings (with printk) 72 | when an allocation cannot be satisfied. 73 | 74 | __GFP_HIGH 75 | This flag marks a high-priority request, which is allowed to consume even the 76 | last pages of memory set aside by the kernel for emergencies. 77 | 78 | __GFP_REPEAT 79 | __GFP_NOFAIL 80 | __GFP_NORETRY 81 | These flags modify how the allocator behaves when it has difficulty satisfying an 82 | allocation. __GFP_REPEAT means “try a little harder” by repeating the attempt— 83 | but the allocation can still fail. The __GFP_NOFAIL flag tells the allocator 84 | never to fail. It works as hard as needed to satisfy the request. __GFP_NORETRY 85 | tells the allocator to give up immediately if the requested memory is not 86 | available. 87 | ``` 88 | 89 | #### Memory Zones 90 | 91 | Both `__GFP_DMA` and `__GFP_HIGHMEM` have a platform-dependent role, although their 92 | use is valid on all platforms. 93 | 94 | The Linux kernel knows about a minimum of three memory zones: 95 | 96 | 1. DMA-capable memory 97 | 2. normal memory 98 | 3. high memory 99 | 100 | While allocation happens in the `normal` memory zone most of the time, setting either of the bits just mentioned requires memory to be allocated from a different zone. We have special memory ranges that fall into the abstraction (a higher abstraction layer than considering all RAM equivalents). 101 | 102 | DMA-capable memory is memory that lives in a preferential address range where peripherals can perform DMA access. On most sane platforms, all memory lives in 103 | this zone. (what if we are insane???) 104 | 105 | High memory is a mechanism used to allow access to (relatively) large amounts of 106 | memory on 32-bit platforms. Only use this if you need a large section of memory - it is a little trickier to work with. 107 | 108 | Whenever a new page is allocated to fulfill a memory allocation request, the kernel 109 | builds a list of zones that can be used in the search. With `__GFP_DMA` specified, only the DMA zone is searched. Different flags can present different combinations of zones to look at. It is important to note that kmalloc cannot allocate high memory. 110 | 111 | In NUMA systems, the allocator attempts to locate memory local to the processor performing the allocation, but there are ways to change this. 112 | 113 | This will be visited again in chapter 15. 114 | 115 | ### The Size Argument 116 | 117 | The kernel takes care of managing the system's physical memory, which is available only in page-sized chunks. Thus, kmalloc is different than normal malloc from user space programs. A simple heap-oriented allocation technique would very quickly run into trouble if everyone needed their own page for everything. 118 | 119 | Linux handles memory allocation by creating a set of pools of memory objects of 120 | fixed sizes. Allocation requests are handled by going to a pool that holds sufficiently large objects and handing an entire memory chunk back to the requester. This technique is very complex, and normally we don't care very much about it with respect to device drivers. It is important to remember that the kernel can allocate only certain predefined, fixed-size byte arrays. The smallest allocation that kmalloc can handle might be 32 or 64 bytes depending on the page size of the system. 121 | 122 | There is also a maximum amount of memory that kmalloc can allocate at once, maybe around 128kB (but there are better ways to allocate larger chuncks that this chapter will cover later). 123 | 124 | ### Lookaside Caches 125 | 126 | A device driver often ends up allocating many objects of the same size, over and over again. We can create special pools of this size called a lookaside cache. Drivers usually do not use these, but USB and SCSI do so we will look at it. 127 | 128 | The cache allocator in Linux is sometimes called a "slab allocator". This is why the functions are declared in ``. The slab allocator implements caches that have a type `kmem_cache_t` and are created with a call to `kmem_cache_create`: 129 | 130 | ```c 131 | kmem_cache_t *kmem_cache_create(const char *name, size_t size, 132 | size_t offset, 133 | unsigned long flags, 134 | void (*constructor)(void *, kmem_cache_t *, 135 | unsigned long flags), 136 | void (*destructor)(void *, kmem_cache_t *, 137 | unsigned long flags)); 138 | ``` 139 | 140 | Wow that is a big constructor! 141 | 142 | - The function creates a new cache object that can host any number of memory areas all of the same size specified by the `size` argument 143 | - The `name` argument is associated with this cache and functions as housekeeping information usable in tracking problems 144 | - Usually it is set to the name of the type of structure that is cached 145 | - The `offset` is the offset of the first object in the page. You will probably use 0 to request the default value. 146 | - `flags` controls how allocation is done and is a bit mask of the following flags: 147 | 148 | ``` 149 | SLAB_NO_REAP 150 | Setting this flag protects the cache from being reduced when the system is 151 | looking for memory. Setting this flag is normally a bad idea; it is important to 152 | avoid restricting the memory allocator’s freedom of action unnecessarily. 153 | 154 | SLAB_HWCACHE_ALIGN 155 | This flag requires each data object to be aligned to a cache line; actual 156 | alignment depends on the cache layout of the host platform. This option can be a 157 | good choice if your cache contains items that are frequently accessed on SMP 158 | machines. The padding required to achieve cache line alignment can end up 159 | wasting significant amounts of memory, however. 160 | 161 | SLAB_CACHE_DMA 162 | This flag requires each data object to be allocated in the DMA memory zone. 163 | ``` 164 | 165 | The constructor and destructor arguments to the function are optional functions but must both be used (you can't just use one or the other). They can be useful, but there are a few constraints you need to keep in mind: 166 | 167 | - A constructor is called when the memory for a set of objects is allocated 168 | - because that memory may hold several objects, the constructor may be called multiple times 169 | - You cannot assume that the constructor will be called as an immediate effect of allocating an object 170 | - Destructors can be called at some unknown future time 171 | - not immediately after an object has been freed 172 | - Constructors and destructors may or may not be allowed to sleep 173 | - This is according to whether they are passed the SLAB_CTOR_ATOMIC flag 174 | 175 | Once a cache of objects is created, you can allocate objects from it by calling `kmem_cache_alloc`. The prototype is: 176 | 177 | ```c 178 | void *kmem_cache_alloc(kmem_cache_t *cache, int flags); 179 | ``` 180 | 181 | The `cache` argument is the cache you have created previously and the flags are the same as the ones you would pass to kmalloc. To free an object, use `kmem_cache_free` with the following prototype: 182 | 183 | ```c 184 | void kmem_cache_free(kmem_cache_t *cache, const void *obj); 185 | ``` 186 | 187 | When the module is unloaded, it should free the cache with: 188 | 189 | ```c 190 | int kmem_cache_destroy(kmem_cache_t *cache); 191 | ``` 192 | 193 | The destroy operation succeeds only if all objects allocated from the cache have been returned to it, so you should check this value as a failure would indicate a leak within the module. 194 | 195 | ### A scull Based on the Slab Caches: scullc :skull: 196 | 197 | scullc is a trimmed-down version of the scull module that implements only the bare device, which is the persistent memory region. While scull uses kmalloc, scullc uses memory caches. 198 | 199 | First, it needs to declare the slab cache: 200 | 201 | ```c 202 | /* declare one cache pointer: use it for all devices */ 203 | kmem_cache_t *scullc_cache; 204 | ``` 205 | 206 | The creation of the slab cache is handled in this way: 207 | 208 | ```c 209 | /* scullc_init: create a cache for our quanta */ 210 | scullc_cache = kmem_cache_create("scullc", scullc_quantum, 211 | 0, SLAB_HWCACHE_ALIGN, NULL, NULL); /* no ctor/dtor */ 212 | 213 | if (!scullc_cache) { 214 | scullc_cleanup(); 215 | return -ENOMEM; 216 | } 217 | ``` 218 | 219 | And allocating memory quanta (the made up unit of space): 220 | 221 | ```c 222 | /* Allocate a quantum using the memory cache */ 223 | if (!dptr->data[s_pos]) { 224 | dptr->data[s_pos] = kmem_cache_alloc(scullc_cache, GFP_KERNEL); 225 | if (!dptr->data[s_pos]) 226 | goto nomem; 227 | memset(dptr->data[s_pos], 0, scullc_quantum); 228 | } 229 | ``` 230 | 231 | And releasing the memory as: 232 | 233 | ```c 234 | for (i = 0; i < qset; i++) 235 | if (dptr->data[i]) 236 | kmem_cache_free(scullc_cache, dptr->data[i]); 237 | ``` 238 | 239 | Then, at unload time, we return the cache to the system with: 240 | 241 | ```c 242 | /* scullc_cleanup: release the cache of our quanta */ 243 | if (scullc_cache) 244 | kmem_cache_destroy(scullc_cache); 245 | ``` 246 | 247 | This method is more efficient and slightly faster than kmalloc. 248 | 249 | ### Memory Pools 250 | 251 | There are places in the kernel where memory allocations cannot be allowed to fail. TO guarantee allocations, developers created an abstraction known as a memory pool. It is really just a form of a lookaside cache that tries to always keep a list of free memory around for use in emergencies. How nice of it to do that. 252 | 253 | A memory pool has a type of `mempool_t` defined in ``. You can create one with `mempool_create` as follows: 254 | 255 | ```c 256 | mempool_t *mempool_create(int min_nr, 257 | mempool_alloc_t *alloc_fn, 258 | mempool_free_t *free_fn, 259 | void *pool_data); 260 | ``` 261 | 262 | - `min_nr` is the minimum number of allocated objects that the pool should always keep around 263 | - actual allocation and freeing of objects is handled by alloc_fn and free_fn with the following prototypes: 264 | 265 | ```c 266 | typedef void *(mempool_alloc_t)(int gfp_mask, void *pool_data); 267 | typedef void (mempool_free_t)(void *element, void *pool_data); 268 | ``` 269 | 270 | - And the final parameter to mempool_create (pool_data) is passed to alloc_fn and free_fn. 271 | 272 | There are two functions (mempool_alloc_slab and mempool_free_slab) that perform the impedance matching between the memory pool allocation prototypes and kmem_cache_alloc and kmem_cache_free. Code that sets up memory pools often looks like this: 273 | 274 | ```c 275 | cache = kmem_cache_create(. . .); 276 | pool = mempool_create(MY_POOL_MINIMUM, 277 | mempool_alloc_slab, mempool_free_slab, 278 | cache); 279 | ``` 280 | 281 | When the pool has been created, objects can be allocated and freed with: 282 | 283 | ```c 284 | void *mempool_alloc(mempool_t *pool, int gfp_mask); 285 | void mempool_free(void *element, mempool_t *pool); 286 | ``` 287 | 288 | When a mempool is created, there will be a pool of pre-allocated objects created that can be used should future calls to mempool_alloc fail. When one of these preallocated pools is freed with mempool free, it is kept in the pool. This also happens if a successfully initialized pool is freed but the total number of preallocated objects is currently below some minimum value. A mempool can be resized with the following call: 289 | 290 | ```c 291 | int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask); 292 | ``` 293 | 294 | - If successful, it resizes the pool to have at least `new_min_nr` objects. 295 | 296 | A mempool can be returned to the system with: 297 | 298 | ```c 299 | void mempool_destroy(mempool_t *pool); 300 | ``` 301 | 302 | - Remember to return all allocated objects before destroying a mempool. 303 | 304 | Using mempools is drivers should be rare because they consume a lot of memory. Allocating and dealing with allocating failures is probably the better route to go. 305 | 306 | ### get_free_page and Friends (friends? what are those?) 307 | 308 | If your module needs a lot of memory, it is better to use a page-oriented technique instead of mempools. To allocate entire pages, use the following: 309 | 310 | ```c 311 | get_zeroed_page(unsigned int flags); 312 | // Returns the pointer to a new page and fills the page with zeros. 313 | 314 | __get_free_page(unsigned int flags); 315 | // Similar to get_zeroed_page, but doesn’t clear the page. This seems like a security bug to me. 316 | 317 | __get_free_pages(unsigned int flags, unsigned int order); 318 | // Allocates and returns a pointer to the first byte of a memory area that is 319 | // potentially several (physically contiguous) pages long but doesn’t zero the area. 320 | ``` 321 | 322 | - `flags` argument is similar to kmalloc. Use `GFP_KERNEL` or `GFP_ATOMIC` and maybe add the `__GFP_DMA` flag for direct-memory-access operations or `__GFP_HIGHMEM` when high memory can be used 323 | - `order` is the base-two logarithm of the number of pages you are requesting or freeing. If order is too big, allocation fails (usually is 10 or 11) 324 | 325 | You can free pages with either of the following functions: 326 | 327 | ```c 328 | void free_page(unsigned long addr); // this is a macro of the function below it 329 | void free_pages(unsigned long addr, unsigned long order); 330 | ``` 331 | 332 | ### A scull Using Whole Pages: scullp 333 | 334 | Memory quanta allocated in the scullp module are whole pages or page sets. The `scullp_order` variable defaults to 0 but can be changed. This is how scullp allocates and deallocates memory: 335 | 336 | ```c 337 | /* Here's the allocation of a single quantum */ 338 | if (!dptr->data[s_pos]) { 339 | dptr->data[s_pos] = 340 | (void *)__get_free_pages(GFP_KERNEL, dptr->order); 341 | if (!dptr->data[s_pos]) 342 | goto nomem; 343 | memset(dptr->data[s_pos], 0, PAGE_SIZE << dptr->order); 344 | } 345 | 346 | /* This code frees a whole quantum-set */ 347 | for (i = 0; i < qset; i++) 348 | if (dptr->data[i]) 349 | free_pages((unsigned long)(dptr->data[i]), 350 | dptr->order); 351 | ``` 352 | 353 | The main advantage of this method over kmalloc is efficiency of memory usage. Allocating by pages wastes no memory, while kmalloc wastes an unpredictable amount of memory because of allocation granularity. 354 | 355 | ### The alloc_pages Interface 356 | 357 | The real core of the Linux page allocator is the function alloc_pages_node with prototypes: 358 | 359 | ```c 360 | struct page *alloc_pages_node(int nid, unsigned int flags, 361 | unsigned int order); 362 | 363 | // Additional macro versions: 364 | struct page *alloc_pages(unsigned int flags, unsigned int order); 365 | struct page *alloc_page(unsigned int flags); 366 | ``` 367 | 368 | - `nid` is the NUMA node ID 369 | - `flags` is the usual `GFP_` allocation flags 370 | - `order` is the size of the allocation (again, in 2^order format) 371 | - The return value is a pointer to the first page structure of the allocated memory or NULL for a failed allocation 372 | - `alloc_pages` simplifies this by putting the memory on the current NUMA node 373 | - `alloc_page` only allocates one page 374 | 375 | To release pages, you should use one of these functions: 376 | 377 | ```c 378 | void __free_page(struct page *page); 379 | void __free_pages(struct page *page, unsigned int order); 380 | void free_hot_page(struct page *page); 381 | void free_cold_page(struct page *page); 382 | ``` 383 | 384 | - The hot page versions are for cache-resident pages 385 | 386 | ### vmalloc and Friends (again, where are these friends coming from?) 387 | 388 | vmalloc allocates a contiguous memory region in *virtual* address space that might be nonconsecutive in physical memory. It returns 0 if an error occurs, and a pointer to a linear memory area of size at least `size` on success. You shouldn't choose vmalloc as your first choice in development because it is slightly less efficient to work with. Try to work with individual pages rather than vmalloc. But here are the prototypes for vmalloc: 389 | 390 | ```c 391 | #include 392 | 393 | void *vmalloc(unsigned long size); 394 | void vfree(void * addr); 395 | void *ioremap(unsigned long offset, unsigned long size); 396 | void iounmap(void * addr); 397 | ``` 398 | 399 | Important notes on vmalloc: 400 | 401 | - Remember: addresses returned by kmalloc, `_get_free_pages`, and vmalloc are virtual addresses 402 | - kmalloc and `_get_free_pages` have a one-to-one mapping to physical memory while vmalloc and ioremap do not follow this 403 | - Use vmalloc for allocating memory for a large sequential buffer that exists only in software 404 | - Memory allocated with vmalloc is released by vfree 405 | - ioremap builds new page tables like vmalloc but does not actually allocate any memory 406 | - The return value of ioremap is a special virtual address 407 | - The virtual address obtained is eventually released by calling iounmap 408 | - ioremap is most useful for mapping the (physical) address of a PCI buffer to (virtual) kernel space 409 | - vmalloc cannot be used in atomic context! 410 | 411 | ### A scull that uses Virtual Addresses: scullv 412 | 413 | The module scullv provides sample code for using vmalloc. The module allocates memory 16 pages at a time. The only difference between scullv and scullp is allocation management. 414 | 415 | How scullv obtains new memory and releases it: 416 | 417 | ```c 418 | /* Allocate a quantum using virtual addresses */ 419 | if (!dptr->data[s_pos]) { 420 | dptr->data[s_pos] = 421 | (void *)vmalloc(PAGE_SIZE << dptr->order); 422 | if (!dptr->data[s_pos]) 423 | goto nomem; 424 | memset(dptr->data[s_pos], 0, PAGE_SIZE << dptr->order); 425 | } 426 | 427 | /* Release the quantum-set */ 428 | for (i = 0; i < qset; i++) 429 | if (dptr->data[i]) 430 | vfree(dptr->data[i]); 431 | ``` 432 | 433 | ### Per-CPU Variables 434 | 435 | When you create a per-CPU variable, each processor on the system gets its own copy of that variable. This is nice because: 436 | 437 | - It requires almost no locking because each CPU works with its own copy 438 | - Per-CPU variables can remain in their respective processors’ caches to speed up programs 439 | 440 | A good example of these variables is found in networking drivers. Rather than deal with the caching and locking issues with the many counters in networking, the we put the statistics counters into per-CPU variables. Updates are lockless and fast. On the rare occasion that user space requests to see the values of the counters, you can simply add up each processor’s version and return the total. 441 | 442 | Declarations for per-CPU variables are found in `` and they can be created with the following macro: 443 | 444 | ```c 445 | DEFINE_PER_CPU(type, name); 446 | 447 | // Can also be used with an array like: 448 | DEFINE_PER_CPU(int[3], my_percpu_array); 449 | ``` 450 | 451 | The main locking feature needed with these variables is to use the `get_cpu_var` macro to access the current processor’s copy of a given variable, and call `put_cpu_var` when you are done. `get_cpu_var` returns an lvalue for the current processor’s version of the variable and disables preemption. The lvalue can also be changed directly. For example: 452 | 453 | ```c 454 | get_cpu_var(sockets_in_use)++; 455 | put_cpu_var(sockets_in_use); 456 | 457 | // And you can access another processors copy with: 458 | per_cpu(variable, int cpu_id); 459 | ``` 460 | 461 | You can dynamically allocate per-CPU variables with: 462 | 463 | ```c 464 | void *alloc_percpu(type); //works most of the time 465 | void *__alloc_percpu(size_t size, size_t align); 466 | ``` 467 | 468 | - The variables can be freed with a call to free_percpu 469 | - Access to these variables is done with: 470 | 471 | ```c 472 | per_cpu_ptr(void *per_cpu_var, int cpu_id); 473 | ``` 474 | 475 | This macro returns a pointer to the version of `per_cpu_var` corresponding to the given `cpu_id`. 476 | 477 | Code using dynamic per-CPU variables tends to look like this: 478 | 479 | ```c 480 | int cpu; 481 | cpu = get_cpu( ) 482 | ptr = per_cpu_ptr(per_cpu_var, cpu); 483 | /* work with ptr */ 484 | put_cpu( ); 485 | ``` 486 | 487 | Per-CPU variables can be exported to modules, but you must use a special version of the macros: 488 | 489 | ```c 490 | EXPORT_PER_CPU_SYMBOL(per_cpu_var); 491 | EXPORT_PER_CPU_SYMBOL_GPL(per_cpu_var); 492 | 493 | // And to access these variables within a module, declare it with: 494 | DECLARE_PER_CPU(type, name); 495 | ``` 496 | 497 | There is usually not much space for per-CPU variables in a system, so keep them small! 498 | 499 | ### Obtaining Large Buffers (getting super buff requires heavy lifting) 500 | 501 | Allocations of large, contiguous memory buffers are prone to failure. So - before you go about trying to allocate a huge region of memory, look at scatter/gather operations in chapter 1. 502 | 503 | #### Acquiring a Dedicated Buffer at Boot Time 504 | 505 | If you really need to do this - you should request it at boot time to have the best odds at actually getting a sufficient memory chunck free. This is the dirty way to do it but can be less prone to failure. A module cannot allocate memory at boot time - only drivers linked directly to the kernel can do that. 506 | 507 | Boot time allocation is performed with one of the following functions: 508 | 509 | ```c 510 | #include 511 | 512 | void *alloc_bootmem(unsigned long size); 513 | void *alloc_bootmem_low(unsigned long size); 514 | void *alloc_bootmem_pages(unsigned long size); 515 | void *alloc_bootmem_low_pages(unsigned long size); 516 | ``` 517 | 518 | Use the low versions if you need DMA operations in your driver. Usually you do not free this memory, but there is a mechanism to do it with: 519 | 520 | ```c 521 | void free_bootmem(unsigned long addr, unsigned long size); 522 | ``` 523 | 524 | It is probably best to avoid this technique altogether for now. Only use it if you *really* *really* need to. And then go to the internet to find out how to best do this. 525 | -------------------------------------------------------------------------------- /Chapter_9_Communicating_with_Hardware.md: -------------------------------------------------------------------------------- 1 | # LDD3 Chapter 9 Notes 2 | 3 | ## Chapter 9: Communicating with Hardware 4 | 5 | Chapter goal: Understand how a driver can access I/O ports and I/O memory while being portable across Linux platforms. This chapter mainly works with the parallel port found on older machines. It may not apply to current computers as much, but the concepts are still important to understand. 6 | 7 | ### I/O Ports and I/O Memory 8 | 9 | Every single peripheral device is controlled by writing and reading its registers (wow, that was simple!). Almost all the time a device has many registers which are accessed at consecutive addresses in either the memory space or the I/O address space. 10 | 11 | At the hardware level, memory regions and I/O regions are the same. Both are accessed by asserting electrical signals on the address bus and control bus and by reading from or writing to the data bus. 12 | 13 | Because peripheral devices are built to fit a peripheral bus, the most popular I/O buses are modeled on the personal computer. Linux implements I/O ports on all computer platforms it runs on, even where the CPU implements a single address space. The use of I/O ports is common for ISA peripheral boards, most PCI devices map registers into a memory address region for speed and effiency purposes with the CPU. 14 | 15 | ### I/O Registers and Conventional Memory 16 | 17 | Someone accessing I/O registers must be careful to avoid being tricked by CPU optimizations that can modify expected I/O behavior. The compiler can cache data into CPU registers without writing them to actual memory. Both write and read operations can operate on cache memory without ever reaching physical RAM! Thus, a driver must ensure that no caching is performed and no read or write reordering takes place when accessing registers. 18 | 19 | To fix this issue, we place a memory barrier between operations that need to be visible to hardware in a particular order. There are four macros to do this: 20 | 21 | ```c 22 | #include 23 | void barrier(void) 24 | /*This function tells the compiler to insert a memory barrier but has no effect on 25 | the hardware. Compiled code stores to memory all values that are currently 26 | modified and resident in CPU registers, and rereads them later when they are 27 | needed. A call to barrier prevents compiler optimizations across the barrier but 28 | leaves the hardware free to do its own reordering. */ 29 | 30 | #include 31 | void rmb(void); 32 | void read_barrier_depends(void); 33 | void wmb(void); 34 | void mb(void); 35 | /*These functions insert hardware memory barriers in the compiled instruction 36 | flow. An rmb (read memory barrier) guarantees that any reads appearing before the 37 | barrier are completed prior to the execution of any subsequent read. wmb 38 | guarantees ordering in write operations, and the mb instruction guarantees both. 39 | Each of these functions is a superset of barrier. */ 40 | 41 | /*read_barrier_depends is a special, weaker form of read barrier. rmb prevents the 42 | reordering of all reads across the barrier, read_barrier_depends blocks 43 | only the reordering of reads that depend on data from other reads. You should 44 | stick to using rmb. */ 45 | 46 | void smp_rmb(void); 47 | void smp_read_barrier_depends(void); 48 | void smp_wmb(void); 49 | void smp_mb(void); 50 | /*These insert hardware barriers only when the kernel is compiled for SMP systems. 51 | Otherwise, they all expand to a simple barrier call.*/ 52 | 53 | //And a typical use of memory barriers in a device driver may have this general form: 54 | writel(dev->registers.addr, io_destination_address); 55 | writel(dev->registers.size, io_size); 56 | writel(dev->registers.operation, DEV_READ); 57 | wmb( ); 58 | writel(dev->registers.control, DEV_GO); 59 | ``` 60 | 61 | Memory buses slow down performance in general, so only use them when you need to. The kernel provides a few useful combinations of variable assignment and memory barrier specification in `` as shown: 62 | 63 | ```c 64 | #define set_mb(var, value) do {var = value; mb( );} while 0 65 | #define set_wmb(var, value) do {var = value; wmb( );} while 0 66 | #define set_rmb(var, value) do {var = value; rmb( );} while 0 67 | ``` 68 | 69 | ### Using I/O Ports 70 | 71 | #### I/O Port Allocation 72 | 73 | You should first get exlusive access to I/O ports before using them. The kernel has a registration interface to allow your driver to claim the port it needs. The core function in that interface is request_region: 74 | 75 | ```c 76 | #include 77 | 78 | struct resource *request_region(unsigned long first, unsigned long n, 79 | const char *name); 80 | ``` 81 | 82 | - Tell the kernel to make use of `n`ports 83 | - Start with the port `first` 84 | - `name` is the name of your device 85 | - Return is non-NULL if allocation succeeds 86 | - If you get a return of NULL, you will not be able to access the ports 87 | - Ports show up in /proc/ioports 88 | 89 | When you are done with I/O ports, return them to the system with: 90 | 91 | ```c 92 | void release_region(unsigned long start, unsigned long n); 93 | ``` 94 | 95 | You can check if a set of I/O ports is available with: 96 | 97 | ```c 98 | int check_region(unsigned long first, unsigned long n); 99 | ``` 100 | 101 | - This will return negative error code if the port is not available 102 | - This function has been deprecated. Do not use it anymore 103 | - Many old drivers use this code 104 | 105 | #### Manipulating I/O Ports 106 | 107 | After a driver has locked the use of I/O ports, it must read and/or wrtie to those ports. Most hardware differentiates between 8, 16, and 32 bit systems. Some examples: 108 | 109 | - Microchip and the DSPIC line of 8 and 16 bit microcontrollers are very popular 110 | - They were the "bees knees" of the early 2000s 111 | - The STM32 family by ST Microelectronics is a popular 32 bit platform 112 | - This is an up and coming platform. ST has recently developed an all-in-one environment for the programming and debugging of these chips. See STMCubeIDE for more info. 113 | - Arduino Uno is an 8 bit microcontroller based on the ATmega328P chip 114 | - Better versions have better hardware, but this is just for reference. 115 | - The Teensy 4.0 microcontroller has a ARM Cortex-M7 processor at 600 MHz and is one of the fastest available today (2020). 116 | - This thing is REALLY powerful for a microcontroller 117 | - Texas Instruments has everything and does everything well. The only downside is that they are really expensive to use in commercial products. They want the big contracts. ST is more likely to do the smaller scale stuff. 118 | 119 | A c program must call different functions to access different size ports. The Linux kernel headers define the following inline functions to access I/O ports: 120 | 121 | ```c 122 | unsigned inb(unsigned port); 123 | void outb(unsigned char byte, unsigned port); 124 | /*Read or write byte ports (eight bits wide). The port argument is defined as 125 | unsigned long for some platforms and unsigned short for others. The return 126 | type of inb is also different across architectures.*/ 127 | 128 | unsigned inw(unsigned port); 129 | void outw(unsigned short word, unsigned port); 130 | /*These functions access 16-bit ports (one word wide); they are not available 131 | when compiling for the S390 platform, which supports only byte I/O. */ 132 | 133 | unsigned inl(unsigned port); 134 | void outl(unsigned longword, unsigned port); 135 | /*These functions access 32-bit ports. longword is declared as either unsigned 136 | long or unsigned int, according to the platform. Like word I/O, “long” I/O is 137 | not available on S390.*/ 138 | ``` 139 | 140 | Note: no 64-bit port I/O operations are defined, even on 64-bit systems. The port address space is at max a 32-bit data path. 141 | 142 | #### I/O Port Access from User Space 143 | 144 | The functions mentioned just before this are mainly meant to be used by device drivers, but they can also be sued from user space. The GNU C library defines them in ``. The following conditions should apply to use them in user space: 145 | 146 | - The program must be compiled with the -O option to force expansion of inline functions 147 | - The ioperm or iopl system calls must be used to get permission to perform I/O operations on ports. ioperm gets permission for individual ports, while iopl gets permission for the entire I/O space. 148 | - The program must run as root to invoke ioperm or iopl. Alternatively, one of its ancestors must have gained port access running as root. 149 | 150 | #### String Operations 151 | 152 | Some processors implement special instructions to transfer a sequence of bytes, words, or longs to and from a single I/O port of the same size. These are called string instructions and they perform a task quicker than C can. The prototypes for string functions are: 153 | 154 | ```c 155 | void insb(unsigned port, void *addr, unsigned long count); 156 | void outsb(unsigned port, void *addr, unsigned long count); 157 | /*Read or write count bytes starting at the memory address addr. Data is read 158 | from or written to the single port port.*/ 159 | 160 | void insw(unsigned port, void *addr, unsigned long count); 161 | void outsw(unsigned port, void *addr, unsigned long count); 162 | //Read or write 16-bit values to a single 16-bit port. 163 | 164 | void insl(unsigned port, void *addr, unsigned long count); 165 | void outsl(unsigned port, void *addr, unsigned long count); 166 | //Read or write 32-bit values to a single 32-bit port. 167 | ``` 168 | 169 | #### Pausing I/O 170 | 171 | Some platforms have problems with timing between the processor and peripheral device. In these situations, a small delay can be inserted after each I/O instruction if another I/O instruction immediately follows. On x86, this is done by performing an `out b` instruction to port 0x80, a normally unused port. Pausing functions are exactly like all of the ones listed above, but they have a `_p` added to the end of them (example: `outb_p` instead of `outb`). 172 | 173 | #### Platform Dependencies 174 | 175 | Here are some more relevant details on the platforms that I am most concerned with: 176 | 177 | ``` 178 | x86_64 179 | The architecture supports all the functions described in this chapter. Port 180 | numbers are of type unsigned short. 181 | 182 | ARM 183 | Ports are memory-mapped, and all functions are supported. String functions are 184 | implemented in C. Ports are of type unsigned int. 185 | ``` 186 | 187 | ### An I/O Port Example 188 | 189 | The sample code we use to show port I/O from within a device driver acts on general-purpose digital I/O ports. These ports are found in most computer systems (are they still?) 190 | 191 | Typically, I/O pins are controlled by two I/O locations: one that allows selecting what pins are used as input and what pins are used as output and one in which you can actually read or write logic levels. This makes the GPIO (general purpose input output). Other times, ports can be only read or only write. Then they may only be controlled by one register telling them to do their function. 192 | 193 | ### An Overview of the Parallel Port 194 | 195 | [Picture of a Parallel Port](https://en.wikipedia.org/wiki/Parallel_port#/media/File:Parallel_computer_printer_port.jpg) 196 | 197 | I won't go into a ton of detail on this port because I don't think they are really used at all anymore. But here are some basics: 198 | 199 | The parallel interface, in its minimal configuration, is made up of three 8-bit ports. The PC standard starts the I/O ports for the first parallel interface at 0x378 and for the second at 0x278. 200 | 201 | - 0x378 is a bidirectional data register 202 | - It connects directly to pins 2–9 on the physical connector 203 | - 0x278 is a read-only status register 204 | - The third port is an output-only control register which mainly controls whether interrupts are enabled or not 205 | - All ports are on the 0-5V TTL logic level 206 | 207 | ### Using I/O Memory 208 | 209 | The main mechanism used to communicate with devices is memory-mapped registers and device memory. Both of these are called I/O memory because the difference between registers and memory is transparent to software. 210 | 211 | I/O memory is a region of RAM-like locations that the device makes available 212 | to the processor over the bus. It can be used for things like holding video data, holding ethernet packets, and implementing registers that behave like I/O ports. 213 | 214 | This chapter focuses mainly on ISA and PCI memory, but other types should be similar in implementation. PCI is discussed in more detail in chapter 12. 215 | 216 | I/O memory may or may not be accessed through page tables. When access does pass through page tables, the kernel must first arrange for the physical address to be visible from your driver. This usually means that you must call ioremap before doing any I/O operations. If no page tables are needed, I/O memory locations look like I/O ports. You can then just read and write to them using proper wrapper functions. 217 | 218 | Whether or not ioremap is required to access I/O memory, direct use of pointers to I/O memory is discouraged. The kernel provides wrapper functions used to access I/O memory that is safe on all platforms and optimized away whenever straight pointer dereferencing can perform the operation. 219 | 220 | ### I/O Memory Allocation and Mapping 221 | 222 | I/O memory regions need to be allocated prior to use. The interface for allocation of memory regions is described in `` and has prototype: 223 | 224 | ```c 225 | struct resource *request_mem_region(unsigned long start, unsigned long len, 226 | char *name); 227 | ``` 228 | 229 | - Allocates a memory region of `len` bytes 230 | - Allocates starting at the bit `start` 231 | - On success, a non-NULL pointer is returned. 232 | - On failure, the return value is NULL. 233 | 234 | All I/O memory allocations are listed in /proc/iomem. 235 | 236 | Memory regions should be free when no longer needed with: 237 | 238 | ```c 239 | void release_mem_region(unsigned long start, unsigned long len); 240 | ``` 241 | 242 | There is also an old, now outdated method to check I/O memory region availability with: 243 | 244 | ```c 245 | int check_mem_region(unsigned long start, unsigned long len); 246 | ``` 247 | 248 | It still shows up sometimes, so it is included here for completeness. 249 | 250 | Next, virtual addresses must be assigned to I/O memory regions with ioremap. Once equipped with ioremap and iounmap, a device driver can access any I/O memory address whether or not it is directly mapped to virtual address space. Here are the prototypes for ioremp: 251 | 252 | ```c 253 | #include 254 | 255 | void *ioremap(unsigned long phys_addr, unsigned long size); 256 | void *ioremap_nocache(unsigned long phys_addr, unsigned long size); 257 | void iounmap(void * addr); 258 | ``` 259 | 260 | - The nocache version is often just identical to ioremap. It was meant to be useful if some control registers were in such an area that write combining or read caching was not desirable. This is rare and often not used. 261 | 262 | ### Accessing I/O Memory 263 | 264 | On some platforms, you may get away with using the return value from ioremap as a 265 | pointer. This is not good though. Instead, a more portable version with functions has been designed as follows: 266 | 267 | To read from I/O memory, use one of the following: 268 | 269 | ```c 270 | unsigned int ioread8(void *addr); 271 | unsigned int ioread16(void *addr); 272 | unsigned int ioread32(void *addr); 273 | ``` 274 | 275 | Where `addr` is an address obtained from ioremap. The return value is what was read from the given I/O memory. 276 | 277 | To write to I/O memory, use one of the following: 278 | 279 | ```c 280 | void iowrite8(u8 value, void *addr); 281 | void iowrite16(u16 value, void *addr); 282 | void iowrite32(u32 value, void *addr); 283 | ``` 284 | 285 | For reading or writing multiple values, use the following: 286 | 287 | ```c 288 | void ioread8_rep(void *addr, void *buf, unsigned long count); 289 | void ioread16_rep(void *addr, void *buf, unsigned long count); 290 | void ioread32_rep(void *addr, void *buf, unsigned long count); 291 | void iowrite8_rep(void *addr, const void *buf, unsigned long count); 292 | void iowrite16_rep(void *addr, const void *buf, unsigned long count); 293 | void iowrite32_rep(void *addr, const void *buf, unsigned long count); 294 | ``` 295 | 296 | - These functions read or write `count` values from the given `buf` to the given `addr` 297 | - `count` is expressed in the size of the data being written 298 | - Ex: ioread32_rep reads `count` 32-bit values starting at `buf` 299 | 300 | If you need to operate on a block of memory instead, use one of the following: 301 | 302 | ```c 303 | void memset_io(void *addr, u8 value, unsigned int count); 304 | void memcpy_fromio(void *dest, void *source, unsigned int count); 305 | void memcpy_toio(void *dest, void *source, unsigned int count); 306 | ``` 307 | 308 | - These functions behave like their C library analogs 309 | 310 | There are some older read/write functions in legacy kernel code that you should watch out for. Some 64-bit platforms also offer readq and writeq, for quad-word (8-byte) memory operations on the PCI bus. 311 | 312 | ### Ports as I/O Memory 313 | 314 | Some hardware has an interesting feature: some versions use I/O ports, while others 315 | use I/O memory. This seems really confusing to me as to why you would do both. The registers exported to the processor are the same in both cases, but the access method is different (this just sounds like a bad time). To minimize the difference between these two access methods, the kernel provides a function called ioport_map with prototype: 316 | 317 | ```c 318 | void *ioport_map(unsigned long port, unsigned int count); 319 | ``` 320 | 321 | - It remaps `count` I/O ports and makes them appear to be I/O memory 322 | - From there on the driver can use ioread8 and related functions on the returned addresses 323 | - This makes it forget that it is using I/O ports at all 324 | 325 | The mapping should be undone when no longer needed with: 326 | 327 | ```c 328 | void ioport_unmap(void *addr); 329 | ``` 330 | 331 | Note: I/O ports must still be allocated with request_region before they can be remapped in this way. 332 | 333 | ### ISA Memory Below 1 MB 334 | 335 | One of the most well-known I/O memory regions is the ISA range found on personal computers. It has a range between 640 KB (0xA0000) and 1 MB (0x100000). This position is due to the fact that in the 1980s 640KB of memory seemed like more than anybody would ever be able to use. Quote Bill Gates: 336 | 337 | "640K ought to be enough for anybody" - he denies ever saying this (probably embarrased about it) 338 | 339 | Anyways, the ISA memory range belongs to the non-directly-mapped class of memory. To demonstrate access to ISA memory, the driver called silly does the trick. The module supplements the functionality of the module short by giving access to the whole 384-KB memory space and by showing all the different I/O functions. 340 | 341 | Because silly provides access to ISA memory, it must first map the physical 342 | ISA addresses into kernel virtual addresses. This is done with ioremap and explained earlier. Code: 343 | 344 | ```c 345 | #define ISA_BASE 0xA0000 346 | #define ISA_MAX 0x100000 /* for general memory access */ 347 | 348 | /* this line appears in silly_init */ 349 | io_base = ioremap(ISA_BASE, ISA_MAX - ISA_BASE); 350 | ``` 351 | - ioremap returns a pointer value that can be used with ioread8 and the other functions 352 | 353 | The following code shows the implementation for read. It makes the address range 0xA0000-0xFFFFF available as a virtual file in the range 0-0x5FFFF. It is structured as a switch case statement for the different access modes. Here is the sillyb case: 354 | 355 | ```c 356 | case M_8: 357 | while (count) { 358 | *ptr = ioread8(add); 359 | add++; 360 | count--; 361 | ptr++; 362 | } 363 | break; 364 | ``` 365 | 366 | The next two devices are /dev/sillyw and /dev/sillyl. They act the same as sillyb, but use 16 and 32-bit functions, respectively. Here is the write implementation of sillyl: 367 | 368 | ```c 369 | case M_32: 370 | while (count >= 4) { 371 | iowrite8(*(u32 *)ptr, add); 372 | add += 4; 373 | count -= 4; 374 | ptr += 4; 375 | } 376 | break; 377 | ``` 378 | 379 | The last device that is a part of the module is /dev/sillycp. It uses `memcpy_*io` functions to perform the same task. 380 | 381 | ```c 382 | case M_memcpy: 383 | memcpy_fromio(ptr, add, count); 384 | break; 385 | ``` 386 | Because ioremap was used to provide access to the ISA memory area, silly must 387 | invoke iounmap when the module is unloaded with: 388 | 389 | ```c 390 | iounmap(io_base); 391 | ``` 392 | 393 | ### isa_readb and Friends (again, what is with the Friends? :two_men_holding_hands: ) 394 | 395 | A look at the kernel source code will show another set of routines with names like isa_readb. Each function just described has an `isa_` equivalent. These functions provide access to ISA memory without the need for a separate ioremap step. Avoid using these! They are temporary band-aids for driver-porting that should be used anymore. It would be sloppy to use these. -------------------------------------------------------------------------------- /Chapter__11_Data_Types.md: -------------------------------------------------------------------------------- 1 | # LDD3 Chapter 11 Notes 2 | 3 | ## Chapter 11: Data Types in the Kernel 4 | 5 | I feel like this chapter should have come sooner in the book (like chapter 2 or 3) but it is fine to mention it in detail here. 6 | 7 | Chapter Goal: Understand portability issues that arise related to the differences in the same data types between platforms. 8 | 9 | Since Linux is meant to be highly portable, it is important to understand the steps you need to take to ensure that your driver will run the same on several different platforms (if necessary). 10 | 11 | Several issues with kernel developers porting code to x86 came from incorrect data typing. Strict data typing and compiling with the `-Wall` and `-Wstrict-prototypes` flags can prevent most bugs. Data types in the kernel fall into three main types: 12 | 13 | 1. Standard C types such as `int` 14 | 2. Explicitly sized types such as `u32` 15 | 3. Types used for specific kernel objects like `pid_t` 16 | 17 | If you follow this chapter carefully, you should be able to develop drivers that work on platforms that you might not even be able to test on. 18 | 19 | ### Use of Standard C Types 20 | 21 | Many programmers through around types like int and long willy nilly without regard to any specifics. Writing good drivers requires a little more attention to avoid typing conflicts and really bizarre bugs. Issues arise when you try to use things like a 2 byte filler or something representing a 4 byte string because normal C data types are not the same size on all architechures. See the included file `datasize` to see the size of various data types on your specific platform. Here is the output from my x86_64 machine: 22 | 23 | ```bash 24 | arch Size: char short int long ptr long-long u8 u16 u32 u64 25 | x86_64 1 2 4 8 8 8 1 2 4 8 26 | ``` 27 | 28 | And here is the output for an i386 computer: 29 | 30 | ```bash 31 | arch Size: char short int long ptr long-long u8 u16 u32 u64 32 | i686 1 2 4 4 4 8 1 2 4 8 33 | ``` 34 | 35 | Already, we can see differences between the long and ptr data types. Here is a more complete table of what happens when you run the program on many different platforms: 36 | 37 | ```bash 38 | arch Size: char short int long ptr long-long u8 u16 u32 u64 39 | i386 1 2 4 4 4 8 1 2 4 8 40 | alpha 1 2 4 8 8 8 1 2 4 8 41 | armv4l 1 2 4 4 4 8 1 2 4 8 42 | ia64 1 2 4 8 8 8 1 2 4 8 43 | m68k 1 2 4 4 4 8 1 2 4 8 44 | mips 1 2 4 4 4 8 1 2 4 8 45 | ppc 1 2 4 4 4 8 1 2 4 8 46 | sparc 1 2 4 4 4 8 1 2 4 8 47 | sparc64 1 2 4 4 4 8 1 2 4 8 48 | x86_64 1 2 4 8 8 8 1 2 4 8 49 | ``` 50 | 51 | Generic memory addresses in the kernel are usually `unsigned long` to exploit that fact that pointers and long ints are always the same size for all the platforms supported by Linux. Think of memory addresses as just an index into a huge memory array. 52 | 53 | ### Assigning an Explicit Size to Data Items 54 | 55 | Sometimes you need to know the size of your data to communicate with user space. The kernel offers the following data types whenever you need to know the size of your data. They are found in `` and included automatically in ``: 56 | 57 | ```c 58 | u8; /* unsigned byte (8 bits) */ 59 | u16; /* unsigned word (16 bits) */ 60 | u32; /* unsigned 32-bit value */ 61 | u64; /* unsigned 64-bit value */ 62 | ``` 63 | 64 | Signed versions of all of these types exist but are rarely used. Simply replace the `u` with an `s` to get the signed version. 65 | 66 | If your are working in user space, you can access these data types with a double underscore like this: `__u8`. These are defined independent of `__KERNEL__`. For example - let's say a driver needs to exchange binary structures with a program running in user space using ioctl. The header files should declare 32 bit fields in the structures as `__u32`. 67 | 68 | These types are Linux specific and may hinder portability to other Unix flavors. Oh well. I hope I don't need to develop for multiple Unix flavors anytime soon. If you do, you can use C99-standard types (there has to be more updated types now?) such as `uint8_t` and `uint32_t`. 69 | 70 | If you see conventional types like `unsigned int` it is likely done for backwards compatibility to the days when Linux had loosy typed structures. 71 | 72 | ### Interface-Specific Types 73 | 74 | Some common kernel data types have their own typedef statements to prevent portability issues. One example is using `pid_t` instead of `int`. By *interface specific*, we mean a type defined by a library in order to provide an interface to a specific data structure. 75 | 76 | A lot of developers (including me) really hate the use of typedefs and would rather see the real type information used directly in the code. However, a lot of legacy code still uses a lot of typedef stuff. 77 | 78 | Many `_t` types are defined in ``. This list is not often useful, however, because when you need a specific data type you will find it in the prototype of the functions you are trying to use. When a driver uses custom types that don't follow the convention, the compiler issues a warning. If you use `-Wall` and are careful to remove warnings, you have a good shot at making portable code. 79 | 80 | One problem comes with printing `_t` data types, since it is not easy to choose the right printk or printf format if these types are architechure dependent. A safe way to do this is to cast the value as the largest possible value to avoid data truncation. 81 | 82 | ### Other Portability Issues 83 | 84 | Besides data typing, portability issues can arise with explicit constant values. Typically code is parameterized using preprocessor macros. Magic numbers = bad! 85 | 86 | #### Time Intervals 87 | 88 | When dealing with time intervals, don't assume there are 1000 jiffies per second. When you calculate time intervals using jiffies, scale your times using `HZ`. The number of jiffies corresponding to `msec` milliseconds is `msec*HZ/1000`. 89 | 90 | #### Page Size 91 | 92 | A memory page is PAGE_SIZE bytes, NOT 4 KB. Use macros PAGE_SIZE and PAGE_SHIFT instead of hard coding numbers for page sizes. PAGE_SHIFT contains the number of bits to shift an address to get its page number. 93 | 94 | Here is one example of the page size issues being made portable: 95 | 96 | If a driver needs 16 KB for temp data, it should not specify and order of 2 to get_free_pages(). You need a more portable solution found by calling get_order: 97 | 98 | ```c 99 | #include 100 | int order = get_order(16*1024); 101 | buf = get_free_pages(GFP_KERNEL, order); 102 | ``` 103 | 104 | - The argument to get_order must be a power of two 105 | 106 | ### Byte Order 107 | 108 | First, here is a good example comparing little and big endian: 109 | [Big Endian and Little Endian Online Reference](https://chortle.ccsu.edu/AssemblyTutorial/Chapter-15/ass15_3.html) 110 | 111 | While most PCs store multibyte values with little endian formatting, some high-level platforms use big-endian formatting. Your code should be written so that it doesn't care about byte ordering. The kernel defines a set of macros that handle conversions between the processors native byte ordering and the data you need to store or load in a specific byte order. Here is one set of macros: 112 | 113 | ```c 114 | //converts a value from whatever the CPU uses to an unsigned, little endian, 32-bit quantity 115 | u32 cpu_to_le32 (u32); 116 | 117 | // converts from the little endian value back to the CPU value 118 | u32 le32_to_cpu (u32); 119 | ``` 120 | 121 | - This works no matter if your CPU uses little/big endian 122 | - ALso works on non-32-bit platforms. 123 | - You can do this with MANY different kinds of little and big endian data types 124 | - These are defined in `` and `` 125 | 126 | ### Data Alignment 127 | 128 | One final problem to consider is what to do with unaligned data. For example - reading a 4-byte word value stored at an address that isn't a multiple of 4 bytes. To do this, use the following macros: 129 | 130 | ```c 131 | #include 132 | get_unaligned(ptr); 133 | put_unaligned(val, ptr); 134 | ``` 135 | 136 | - These macros are typeless 137 | - They work for every data item, no matter the byte length 138 | - They are defined with any kernel version 139 | 140 | To write data structures for data items that can be moved across architechures, always enforce natural alignment of the data items along with standardizing on a specific endianness. 141 | 142 | - Natural alignment means storing data items at an address that is a multiple of their size (for example, 8-byte items go in an address multiple of 8). 143 | - Then use filler fields to avoid leaving holes in that data structure. 144 | 145 | See the sample program dataalign in the misc-progs directory of the sample code to show how alignment is enforced by the compiler. 146 | 147 | The output from my system is: 148 | 149 | ```bash 150 | arch Align: char short int long ptr long-long u8 u16 u32 u64 151 | x86_64 1 2 4 8 8 8 1 2 4 8 152 | ``` 153 | 154 | And the output from the kdataalign kernel module for my system is shown below: 155 | 156 | ```bash 157 | [Mar17 19:42] kdataalign: unknown parameter 'kdataalign' ignored 158 | [ +0.000048] arch Align: char short int long ptr long-long u8 u16 u32 u64 159 | [ +0.000002] x86_64 1 2 4 8 8 8 1 2 4 8 160 | ``` 161 | 162 | A compiler may also automatically pad without telling you, and this could cause issues. So be aware of this. The workaround for this issue is to tell the compiler that the structure must be packed with no fillers added. One example is found in the kernel header file `` which defines data structures used in interfacing with the x86 BIOS: 163 | 164 | ```c 165 | struct { 166 | u16 id; 167 | u64 lun; 168 | u16 reserved1; 169 | u32 reserved2; 170 | } __attribute__ ((packed)) scsi; 171 | ``` 172 | 173 | Without the `__attribute__ ((packed))`, the lun field would be preceded by two filler bytes or six if we compile the structure on a 64-bit platform. 174 | 175 | ### Pointers and Error Values (I can point to errors all day long) 176 | 177 | Several internal kernel functions return a pointer value to the caller. These functions can also fail (welcome to the club). In most cases, failure is indicated by returning a NULL pointer value. While this works, it does very little to describe the actual nature of the problem. There are times when the caller needs an actual error code so that the right decision can be made as to what to do next in a program. 178 | 179 | A function returning a pointer type can return an error value with: 180 | 181 | ```c 182 | void *ERR_PTR(long error); 183 | ``` 184 | 185 | - Error is the usual negative error code 186 | 187 | The caller can use `IS_ERR` to test whether a returned pointer is an error code or not with: 188 | 189 | ```c 190 | long IS_ERR(const void *ptr); 191 | ``` 192 | 193 | THe actual error code can be extracted with: 194 | 195 | ```c 196 | long PTR_ERR(const void *ptr); 197 | ``` 198 | 199 | - Only use `PTR_ERR` on a value for which `IS_ERR` returns a true value. 200 | 201 | 202 | ### Linked Lists 203 | 204 | OS kernels often need to maintain lists of data structures. Developers have created a standard implementation of circular, doubly linked lists. People who need to manipulate lists are encouraged to use this facility. 205 | 206 | Linked lists in the kernel do not perform locking. You need to implement your own locking to use these responsibly. To use the list mechanism, include the file `` and look for the structure of type `list_head`: 207 | 208 | ```c 209 | struct list_head { 210 | struct list_head *next, *prev; 211 | }; 212 | ``` 213 | 214 | - Linked lists used in real code are usually made up of some type of structure 215 | - Each one describes one entry in the list 216 | - You need only embed a `list_head` inside the structures that make up the list 217 | 218 | An example in your code may look like this: 219 | 220 | ```c 221 | struct todo_struct { 222 | struct list_head list; 223 | int priority; /* driver specific */ 224 | /* ... add other driver-specific fields */ 225 | }; 226 | ``` 227 | 228 | List heads must be initialized prior to use with the INIT_LIST_HEAD macro. A “to do” list head could be declared and initialized with: 229 | 230 | ```c 231 | struct list_head todo_list; 232 | INIT_LIST_HEAD(&todo_list); 233 | ``` 234 | 235 | Alternatively, lists can be initialized at compile time: 236 | 237 | ```c 238 | LIST_HEAD(todo_list); 239 | ``` 240 | 241 | Review of doubly linked lists: 242 | [Doubly Linked List \| Set 1 (Introduction and Insertion) - GeeksforGeeks](https://www.geeksforgeeks.org/doubly-linked-list/) 243 | 244 | Several functions are defined in `` that work with lists: 245 | 246 | ``` 247 | list_add(struct list_head *new, struct list_head *head); 248 | Adds the new entry immediately after the list head—normally at the beginning of 249 | the list. Therefore, it can be used to build stacks. Note, however, that the head 250 | need not be the nominal head of the list. If you pass a list_head structure that 251 | happens to be in the middle of the list somewhere, the new entry goes immediately 252 | after it. Since Linux lists are circular, the head of the list is not generally 253 | different from any other entry. 254 | 255 | list_add_tail(struct list_head *new, struct list_head *head); 256 | Adds a new entry just before the given list head—at the end of the list, in other 257 | words. list_add_tail can, thus, be used to build first-in first-out queues. 258 | 259 | list_del(struct list_head *entry); 260 | list_del_init(struct list_head *entry); 261 | The given entry is removed from the list. If the entry might ever be reinserted 262 | into another list, you should use list_del_init, which reinitializes the linked list 263 | pointers. 264 | 265 | list_move(struct list_head *entry, struct list_head *head); 266 | list_move_tail(struct list_head *entry, struct list_head *head); 267 | The given entry is removed from its current list and added to the beginning of 268 | head. To put the entry at the end of the new list, use list_move_tail instead. 269 | 270 | list_empty(struct list_head *head); 271 | Returns a nonzero value if the given list is empty. 272 | 273 | list_splice(struct list_head *list, struct list_head *head); 274 | Joins two lists by inserting list immediately after head. 275 | 276 | ``` 277 | 278 | The `list_head` structures are good for implementing a list of like structures. However, the invoking program is usually more interested in the larger structures that make up the list as a whole. 279 | 280 | A macro called list_entry is provided that maps a list_head structure pointer back into a pointer to the structure that contains it. It is used like this: 281 | 282 | ```c 283 | list_entry(struct list_head *ptr, type_of_struct, field_name); 284 | ``` 285 | 286 | - `ptr` is a pointer to the `struct list_head` being used 287 | - `type_of_struct` is the type of the structure containing the `ptr` 288 | - `field_name` is the name of the list field within the structure 289 | 290 | To turn a list entry into its containing structure, you could do this (where tehe list field is just called `list`): 291 | 292 | ```c 293 | struct todo_struct *todo_ptr = 294 | list_entry(listptr, struct todo_struct, list); 295 | ``` 296 | 297 | The author claims that the traversal of linked lists is easy. We will see. Here is an example given for keeping the list of todo_struct items sorted in descending priority order. A function to add a new entry would look like this: 298 | 299 | ```c 300 | void todo_add_entry(struct todo_struct *new) 301 | { 302 | struct list_head *ptr; 303 | struct todo_struct *entry; 304 | for (ptr = todo_list.next; ptr != &todo_list; ptr = ptr->next) { 305 | entry = list_entry(ptr, struct todo_struct, list); 306 | if (entry->priority < new->priority) { 307 | list_add_tail(&new->list, ptr); 308 | return; 309 | } 310 | } 311 | list_add_tail(&new->list, &todo_struct) 312 | } 313 | ``` 314 | 315 | However, instead of doing this there is a better method using predefined macros for creating and iterating through linked lists. The previous example could be rewritten as: 316 | 317 | ```c 318 | void todo_add_entry(struct todo_struct *new) 319 | { 320 | struct list_head *ptr; 321 | struct todo_struct *entry; 322 | 323 | list_for_each(ptr, &todo_list) { 324 | entry = list_entry(ptr, struct todo_struct, list); 325 | if (entry->priority < new->priority) { 326 | list_add_tail(&new->list, ptr); 327 | return; 328 | } 329 | } 330 | list_add_tail(&new->list, &todo_struct) 331 | } 332 | ``` 333 | 334 | Use the macros as much as possible. It will probably work better than your code and you will make less mistakes. A few variants of these macros exist: 335 | 336 | ``` 337 | list_for_each(struct list_head *cursor, struct list_head *list) 338 | Creates a for loop that executes once with cursor pointing at each 339 | successive entry in the list. Be careful about changing the list while iterating 340 | through it. 341 | 342 | list_for_each_prev(struct list_head *cursor, struct list_head *list) 343 | This one iterates backwards through the list 344 | 345 | list_for_each_safe(struct list_head *cursor, struct list_head *next, struct list_head *list) 346 | If your loop may delete entries in the list, use this version. It simply stores the 347 | next entry in the list in next at the beginning of the loop, so it does not get 348 | confused if the entry pointed to by cursor is deleted. 349 | 350 | list_for_each_entry(type *cursor, struct list_head *list, member) 351 | list_for_each_entry_safe(type *cursor, type *next, struct list_head *list, member) 352 | These ease the process of dealing with a list containing a given type of 353 | structure. Cursor is a pointer to the containing structure type. Member 354 | is the name of the list_head structure within the containing structure. With 355 | these macros, there is no need to put list_entry calls inside the loop. 356 | ``` 357 | 358 | Inside `` are additional declarations. hlist is a doubly linked list with a separate, single-pointer list head type used for hash tables. There is some other stuff related to a Read-Copy-Update mechanism. You have options if you need them. 359 | -------------------------------------------------------------------------------- /Code_Examples/Block_Driver/Makefile: -------------------------------------------------------------------------------- 1 | MODULE_NAME := domsblockdev 2 | obj-m := $(MODULE_NAME).o 3 | 4 | OBJ_LIST := domblockdev.o 5 | $(MODULE_NAME)-y += $(OBJ_LIST) 6 | 7 | ccflags-y := -O2 8 | 9 | KERNELDIR := /lib/modules/$(shell uname -r)/build 10 | 11 | all: domblockdev 12 | 13 | domblockdev: 14 | make -C $(KERNELDIR) M=$(PWD) modules 15 | -------------------------------------------------------------------------------- /Code_Examples/Block_Driver/README.md: -------------------------------------------------------------------------------- 1 | # The Block Party 2 | 3 | Let's have some fun with block devices and Shakespeare. I promise this is more fun than it sounds. Well, for me it is anyways. 4 | 5 | Start by downloading the four files here: `domblockdev.c`, the `Makefile`, `fun_text`, and `sonnet`. Next, use `make` from the command line to create the usual kernel object. This time it will be called `domsblockdev.ko` (creatively named after some person named Dom). Insert the module like usual: 6 | 7 | ```shell 8 | $ insmod domsblockdev.ko 9 | ``` 10 | 11 | With dmesg looking like this: 12 | 13 | ```shell 14 | [ +13.834971] domblockdev: The block device was created! Congrats! 15 | ``` 16 | 17 | First, let's check on some info about our ramdisk that was just created: 18 | 19 | ```shell 20 | $ cat /sys/block/domblockdev-0/uevent 21 | 22 | MAJOR=252 23 | MINOR=0 24 | DEVNAME=domblockdev-0 25 | DEVTYPE=disk 26 | ``` 27 | 28 | This all looks good. Now, let's write some info to the disk. Let's start with the sample text found in `fun_text`: 29 | 30 | ```shell 31 | $ dd if=fun_text of=/dev/domblockdev-0 bs=512 count=1 seek=0 32 | ``` 33 | 34 | - This takes the text from the file fun_text and writes it to the start of domblockdev-0 35 | - We have set the block size to 512 (a good default because the kernel counts in 512 byte increments for file transfer) 36 | - We set the count to 1 (number of blocks to transfer) 37 | - We set seek to 0 (the offest of where to start writing, in 512-byte chunks) 38 | 39 | dmesg will look like this while the write takes place: 40 | 41 | ```shell 42 | [Apr26 14:41] domblockdev: Device was opened 43 | [ +0.000101] domblockdev: Request start from sector 0 44 | [ +0.000004] domblockdev: Request process 4096 bytes 45 | [ +0.000143] domblockdev: Request start from sector 0 46 | [ +0.000006] domblockdev: Request process 4096 bytes 47 | [ +0.000098] domblockdev: Device was closed 48 | ``` 49 | 50 | And we can read our ramdisk now with this command to see the contents of that file: 51 | 52 | ``` 53 | $ cat /dev/domblockdev-0 54 | 55 | Hello! You are copying this data from the disk in user space 56 | into your block driver! If you can read all of this, you did it correctly! 57 | ``` 58 | 59 | Now, let's have a bit more fun with Shakespeare. I have included one of his wonderful sonnets in a file called `sonnet` that is about 619 bytes long (longer than that magic 512 byte size thing that the kernel likes). Let's start by writing the sonnet to the ram disk AFTER our current text that we have. We do that with: 60 | 61 | ```shell 62 | $ dd if=sonnet of=/dev/domblockdev-0 bs=512 count=2 seek=1 63 | 64 | 65 | 1+1 records in 66 | 1+1 records out 67 | 619 bytes copied, 0.00066355 s, 933 kB/s 68 | ``` 69 | 70 | - We use sonnet as the `if` argument for dd to write that data to the disk (see `man dd` for more info). 71 | - We use the same block size of 512 bytes 72 | - We use a count of 2 because our file is larger than the 512 size 73 | - We set seek to 1 to write AFTER the first block of 512 bytes that we already wrote to before 74 | 75 | The result is the ram disk looks like this: 76 | 77 | ```shell 78 | $ cat /dev/domblockdev-0 79 | 80 | Hello! You are copying this data from the disk in user space into your block driver! 81 | If you can read all of this, you did it correctly! 82 | Shall I compare thee to a summer's day? 83 | Thou art more lovely and more temperate: 84 | Rough winds do shake the darling buds of May, 85 | And summer's lease hath all too short a date: 86 | Sometime too hot the eye of heaven shines, 87 | And often is his gold complexion dimm'd; 88 | And every fair from fair sometime declines, 89 | By chance or nature's changing course untrimm'd; 90 | But thy eternal summer shall not fade 91 | Nor lose possession of that fair thou owest; 92 | Nor shall Death brag thou wander'st in his shade, 93 | When in eternal lines to time thou growest: 94 | So long as men can breathe or eyes can see, 95 | So long lives this and this gives life to thee. 96 | ``` 97 | 98 | There we have it! We have now stored multiple different files into different locations on the ramdisk. Now, lets dump all of the ramdisk data into a file on our real disk: 99 | 100 | ```shell 101 | $ dd if=/dev/domblockdev-0 of=testoutput bs=512 count=3 seek=0 102 | 103 | 3+0 records in 104 | 3+0 records out 105 | 1536 bytes (1.5 kB, 1.5 KiB) copied, 0.00057702 s, 2.7 MB/s 106 | ``` 107 | 108 | - Here we use /dev/domblockdev-0 as the `if` argument 109 | - We want to copy from this device now 110 | - We create a new file called `testoutput` to dump the data into 111 | - Same block size 112 | - Count is now 3 to include ALL the data we wrote 113 | - Seek is 0 because we started writing data at the beginning of our ramdisk 114 | 115 | We can then check the file we just created with: 116 | 117 | ```shell 118 | $ cat testoutput 119 | 120 | Hello! You are copying this data from the disk in user space into your block driver! 121 | If you can read all of this, you did it correctly! 122 | Shall I compare thee to a summer's day? 123 | Thou art more lovely and more temperate: 124 | Rough winds do shake the darling buds of May, 125 | And summer's lease hath all too short a date: 126 | Sometime too hot the eye of heaven shines, 127 | And often is his gold complexion dimm'd; 128 | And every fair from fair sometime declines, 129 | By chance or nature's changing course untrimm'd; 130 | But thy eternal summer shall not fade 131 | Nor lose possession of that fair thou owest; 132 | Nor shall Death brag thou wander'st in his shade, 133 | When in eternal lines to time thou growest: 134 | So long as men can breathe or eyes can see, 135 | So long lives this and this gives life to thee. 136 | ``` 137 | 138 | It matched! Look at that! Now, play around with this driver and see how it works in detail with reading and writing. There are a lot of cool things you can do to explore (and break) this driver. Have fun! 139 | -------------------------------------------------------------------------------- /Code_Examples/Block_Driver/domblockdev.c: -------------------------------------------------------------------------------- 1 | // Sample Ramdisk for Kernel Versions 5.3+ 2 | // Based off the example provided by CodeImp for Kernel 5.0 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include //for struct hd_geometry 13 | #include //for CDROM_GET_CAPABILITY 14 | 15 | // constants - instead defines 16 | static const char* _device_name = "domblockdev"; 17 | static const size_t _buffer_size = 16 * PAGE_SIZE; 18 | 19 | // types 20 | typedef struct domblockdev_cmd_s { 21 | } domblockdev_cmd_t; 22 | 23 | // The internal representation of our device 24 | typedef struct domblockdev_device_s { 25 | sector_t capacity; // Device size in bytes 26 | u8* data; // The data aray. u8 - 8 bytes 27 | atomic_t open_counter; // How many openers 28 | struct blk_mq_tag_set tag_set; 29 | struct request_queue *queue; // For mutual exclusion 30 | struct gendisk *disk; // The gendisk structure 31 | } domblockdev_device_t; 32 | 33 | // global variables 34 | static int _domblockdev_major = 0; 35 | static domblockdev_device_t* _domblockdev_device = NULL; 36 | 37 | // functions 38 | static int domblockdev_allocate_buffer(domblockdev_device_t* dev) { 39 | dev->capacity = _buffer_size >> SECTOR_SHIFT; 40 | dev->data = kmalloc(dev->capacity << SECTOR_SHIFT, GFP_KERNEL); // 41 | if (dev->data == NULL) { 42 | printk(KERN_WARNING "domblockdev: vmalloc failure\n"); 43 | return -ENOMEM; 44 | } 45 | 46 | return 0; 47 | } 48 | 49 | static void domblockdev_free_buffer(domblockdev_device_t* dev) { 50 | if (dev->data) { 51 | kfree(dev->data); 52 | dev->data = NULL; 53 | dev->capacity = 0; 54 | } 55 | } 56 | 57 | static void domblockdev_remove_device(void) { 58 | domblockdev_device_t* dev = _domblockdev_device; 59 | if (dev == NULL) 60 | return; 61 | 62 | if (dev->disk) 63 | del_gendisk(dev->disk); 64 | 65 | if (dev->queue) { 66 | blk_cleanup_queue(dev->queue); 67 | dev->queue = NULL; 68 | } 69 | 70 | if (dev->tag_set.tags) 71 | blk_mq_free_tag_set(&dev->tag_set); 72 | 73 | if (dev->disk) { 74 | put_disk(dev->disk); 75 | dev->disk = NULL; 76 | } 77 | 78 | domblockdev_free_buffer(dev); 79 | kfree(dev); 80 | _domblockdev_device = NULL; 81 | printk(KERN_WARNING "domblockdev: The block device was removed!\n"); 82 | } 83 | 84 | static int do_simple_request(struct request *rq, unsigned int *nr_bytes) { 85 | int ret = 0; 86 | struct bio_vec bvec; 87 | struct req_iterator iter; 88 | domblockdev_device_t *dev = rq->q->queuedata; 89 | loff_t pos = blk_rq_pos(rq) << SECTOR_SHIFT; 90 | loff_t dev_size = (loff_t)(dev->capacity << SECTOR_SHIFT); 91 | 92 | printk(KERN_WARNING "domblockdev: Request start from sector %lld \n", blk_rq_pos(rq)); 93 | 94 | rq_for_each_segment(bvec, rq, iter) { 95 | unsigned long b_len = bvec.bv_len; 96 | void* b_buf = page_address(bvec.bv_page) + bvec.bv_offset; 97 | 98 | if ((pos + b_len) > dev_size) 99 | b_len = (unsigned long)(dev_size - pos); 100 | if (rq_data_dir(rq)) //WRITE data to ramdisk 101 | memcpy(dev->data + pos, b_buf, b_len); 102 | else //READ data from ramdisk 103 | memcpy(b_buf, dev->data + pos, b_len); 104 | 105 | pos += b_len; 106 | *nr_bytes += b_len; 107 | } 108 | 109 | return ret; 110 | } 111 | 112 | static blk_status_t _queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data* bd) { 113 | unsigned int nr_bytes = 0; 114 | blk_status_t status = BLK_STS_OK; 115 | struct request *rq = bd->rq; 116 | blk_mq_start_request(rq); //we cannot use any locks that make the thread sleep 117 | 118 | if (do_simple_request(rq, &nr_bytes) != 0) 119 | status = BLK_STS_IOERR; 120 | 121 | printk(KERN_WARNING "domblockdev: Request process %d bytes\n", nr_bytes); 122 | 123 | if (blk_update_request(rq, status, nr_bytes)) //GPL-only symbol 124 | BUG(); 125 | 126 | __blk_mq_end_request(rq, status); 127 | 128 | return BLK_STS_OK;//always return ok 129 | } 130 | 131 | static struct blk_mq_ops _mq_ops = { 132 | .queue_rq = _queue_rq, 133 | }; 134 | 135 | static int _open(struct block_device *bdev, fmode_t mode) { 136 | domblockdev_device_t* dev = bdev->bd_disk->private_data; 137 | if (dev == NULL) { 138 | printk(KERN_WARNING "domblockdev: Invalid disk private_data\n"); 139 | return -ENXIO; 140 | } 141 | atomic_inc(&dev->open_counter); 142 | printk(KERN_WARNING "domblockdev: Device was opened\n"); 143 | 144 | return 0; 145 | } 146 | 147 | static void _release(struct gendisk *disk, fmode_t mode) { 148 | domblockdev_device_t* dev = disk->private_data; 149 | if (dev) { 150 | atomic_dec(&dev->open_counter); 151 | printk(KERN_WARNING "domblockdev: Device was closed\n"); 152 | } 153 | else 154 | printk(KERN_WARNING "domblockdev: Invalid disk private_data\n"); 155 | } 156 | 157 | static int _getgeo(domblockdev_device_t* dev, struct hd_geometry* geo) { 158 | sector_t quotient; 159 | geo->start = 0; 160 | if (dev->capacity > 63) { 161 | geo->sectors = 63; 162 | quotient = (dev->capacity + (63 - 1)) / 63; 163 | 164 | if (quotient > 255) { 165 | geo->heads = 255; 166 | geo->cylinders = (unsigned short)((quotient + (255 - 1)) / 255); 167 | } 168 | else { 169 | geo->heads = (unsigned char)quotient; 170 | geo->cylinders = 1; 171 | } 172 | } 173 | else { 174 | geo->sectors = (unsigned char)dev->capacity; 175 | geo->cylinders = 1; 176 | geo->heads = 1; 177 | } 178 | return 0; 179 | } 180 | 181 | static int _ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { 182 | int ret = -ENOTTY; 183 | domblockdev_device_t* dev = bdev->bd_disk->private_data; 184 | printk(KERN_WARNING "domblockdev: ioctl %x received\n", cmd); 185 | 186 | switch (cmd) { 187 | case HDIO_GETGEO: { 188 | struct hd_geometry geo; 189 | ret = _getgeo(dev, &geo ); 190 | 191 | if (copy_to_user((void *)arg, &geo, sizeof(struct hd_geometry))) 192 | ret = -EFAULT; 193 | else 194 | ret = 0; 195 | break; 196 | } 197 | case CDROM_GET_CAPABILITY: {//0x5331 / * get capabilities * / 198 | struct gendisk *disk = bdev->bd_disk; 199 | if (bdev->bd_disk && (disk->flags & GENHD_FL_CD)) 200 | ret = 0; 201 | else 202 | ret = -EINVAL; 203 | break; 204 | } 205 | } 206 | 207 | return ret; 208 | } 209 | 210 | static const struct block_device_operations _fops = { 211 | .owner = THIS_MODULE, 212 | .open = _open, 213 | .release = _release, 214 | .ioctl = _ioctl, 215 | }; 216 | 217 | // For adding the block device disk to the system 218 | static int domblockdev_add_device(void) { 219 | int ret = 0; 220 | 221 | domblockdev_device_t* dev = kzalloc(sizeof(domblockdev_device_t), GFP_KERNEL); 222 | if (dev == NULL) { 223 | printk(KERN_WARNING "domblockdev: Failed to allocate %ld bytes\n", sizeof(domblockdev_device_t)); 224 | return -ENOMEM; 225 | } 226 | _domblockdev_device = dev; 227 | 228 | do{ 229 | ret = domblockdev_allocate_buffer(dev); 230 | if(ret) 231 | break; 232 | 233 | {// configure tag_set 234 | dev->tag_set.ops = &_mq_ops; 235 | dev->tag_set.nr_hw_queues = 1; 236 | dev->tag_set.queue_depth = 128; 237 | dev->tag_set.numa_node = NUMA_NO_NODE; 238 | dev->tag_set.cmd_size = sizeof(domblockdev_cmd_t); 239 | dev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; 240 | dev->tag_set.driver_data = dev; 241 | 242 | ret = blk_mq_alloc_tag_set(&dev->tag_set); 243 | if (ret) { 244 | printk(KERN_WARNING "domblockdev: Failed to allocate tag set\n"); 245 | break; 246 | } 247 | } 248 | 249 | {//configure queue 250 | struct request_queue *queue = blk_mq_init_queue(&dev->tag_set); 251 | if (IS_ERR(queue)) { 252 | ret = PTR_ERR(queue); 253 | printk(KERN_WARNING "domblockdev: Failed to allocate queue\n"); 254 | break; 255 | } 256 | dev->queue = queue; 257 | } 258 | dev->queue->queuedata = dev; 259 | 260 | {// configure disk 261 | struct gendisk *disk = alloc_disk(1); //only one partition 262 | if (disk == NULL) { 263 | printk(KERN_WARNING "domblockdev: Failed to allocate disk\n"); 264 | ret = -ENOMEM; 265 | break; 266 | } 267 | disk->flags |= GENHD_FL_NO_PART_SCAN; //only one partition 268 | disk->flags |= GENHD_FL_REMOVABLE; 269 | disk->major = _domblockdev_major; 270 | disk->first_minor = 0; 271 | disk->fops = &_fops; 272 | disk->private_data = dev; 273 | disk->queue = dev->queue; 274 | sprintf(disk->disk_name, "domblockdev-%d", 0); 275 | set_capacity(disk, dev->capacity); 276 | 277 | dev->disk = disk; 278 | add_disk(disk); 279 | } 280 | printk(KERN_WARNING "domblockdev: The block device was created! Congrats!\n"); 281 | }while(false); // The reason for the do...while loop is to add individual break points for each section 282 | 283 | if (ret){ 284 | domblockdev_remove_device(); 285 | printk(KERN_WARNING "domblockdev: Failed add block device\n"); 286 | } 287 | 288 | return ret; 289 | } 290 | 291 | static int __init domblockdev_init(void) { 292 | int ret = 0; 293 | 294 | _domblockdev_major = register_blkdev(_domblockdev_major, _device_name); 295 | if (_domblockdev_major <= 0){ 296 | printk(KERN_WARNING "domblockdev: Unable to get major number\n"); 297 | return -EBUSY; 298 | } 299 | ret = domblockdev_add_device(); 300 | if (ret) 301 | unregister_blkdev(_domblockdev_major, _device_name); 302 | 303 | return ret; 304 | } 305 | 306 | static void __exit domblockdev_exit(void) { 307 | domblockdev_remove_device(); 308 | if (_domblockdev_major > 0) 309 | unregister_blkdev(_domblockdev_major, _device_name); 310 | } 311 | 312 | module_init(domblockdev_init); 313 | module_exit(domblockdev_exit); 314 | 315 | MODULE_LICENSE("GPL"); 316 | MODULE_AUTHOR("DOM"); 317 | -------------------------------------------------------------------------------- /Code_Examples/Block_Driver/fun_text: -------------------------------------------------------------------------------- 1 | Hello! You are copying this data from the disk in user space into your block driver! If you can read all of this, you did it correctly! 2 | -------------------------------------------------------------------------------- /Code_Examples/Block_Driver/sonnet: -------------------------------------------------------------------------------- 1 | Shall I compare thee to a summer's day? 2 | Thou art more lovely and more temperate: 3 | Rough winds do shake the darling buds of May, 4 | And summer's lease hath all too short a date: 5 | Sometime too hot the eye of heaven shines, 6 | And often is his gold complexion dimm'd; 7 | And every fair from fair sometime declines, 8 | By chance or nature's changing course untrimm'd; 9 | But thy eternal summer shall not fade 10 | Nor lose possession of that fair thou owest; 11 | Nor shall Death brag thou wander'st in his shade, 12 | When in eternal lines to time thou growest: 13 | So long as men can breathe or eyes can see, 14 | So long lives this and this gives life to thee. 15 | -------------------------------------------------------------------------------- /Code_Examples/Char_Driver/Makefile: -------------------------------------------------------------------------------- 1 | # If KERNELRELEASE is defined, we've been invoked from the 2 | # kernel build system and can use its language. 3 | ARCH := x86 4 | C_FLAGS := -Wall 5 | 6 | ifneq ($(KERNELRELEASE),) 7 | obj-m := main.o 8 | # Otherwise we were called directly from the command 9 | # line; invoke the kernel build system. 10 | else 11 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 12 | PWD := $(shell pwd) 13 | default: 14 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 15 | endif 16 | -------------------------------------------------------------------------------- /Code_Examples/Char_Driver/README.md: -------------------------------------------------------------------------------- 1 | ### Alright this is a bit more than Hello_world 2 | 3 | First, take a scroll through the source file. It has many comments! 4 | 5 | First, make main.ko from the source and makefile. When you insert the module you should see this output: 6 | 7 | ```shell 8 | [Apr25 20:52] Successfully started DOMCHARDEV-(237, 0) 9 | [ +0.000094] Successfully started DOMCHARDEV-(237, 1) 10 | [ +0.000101] Successfully started DOMCHARDEV-(237, 2) 11 | [ +0.000081] Successfully started DOMCHARDEV-(237, 3) 12 | ``` 13 | 14 | One thing you can do is read from the devices: 15 | 16 | ``` 17 | $ head -1 /dev/domchardev-0 18 | 19 | Hello from the kernel world! This is Dom's char device! 20 | ``` 21 | 22 | And corresponding dmesg output: 23 | 24 | ```shell 25 | [ +4.833332] DOMCHARDEV-0: Device open 26 | [ +0.000012] Reading device number: (237, 0) 27 | [ +0.000031] DOMCHARDEV-0: Device close 28 | ``` 29 | 30 | Another thing you can do is write to the device: 31 | 32 | ```shell 33 | $ echo "hi there!" > /dev/domchardev-0 34 | ``` 35 | 36 | And corresponding dmesg output: 37 | 38 | ```shell 39 | [ +15.280692] DOMCHARDEV-0: Device open 40 | [ +0.000027] Writing device number: (237, 0) 41 | [ +0.000002] Copied 10 bytes from the user 42 | [ +0.000003] Data from the user: hi there! 43 | [ +0.000008] DOMCHARDEV-0: Device close 44 | ``` 45 | 46 | You can also access the uevent structure: 47 | 48 | ```shell 49 | $ cat /sys/dev/char/237\:0/uevent # replace with your device major/minor numbers! 50 | 51 | MAJOR=237 52 | MINOR=0 53 | DEVNAME=domchardev-0 54 | DEVMODE=0666 55 | ``` 56 | -------------------------------------------------------------------------------- /Code_Examples/Char_Driver/main.c: -------------------------------------------------------------------------------- 1 | // Example Char Driver on Linux 2 | // Originally inspired by Oleg Kutkov 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | //Set this to whatever you want - it will create more/less virtual devices 13 | #define MAX_DEVICES 4 14 | 15 | // Define the functions for open, release, ioctl, read, and write for the char driver 16 | static int dom_chardev_open (struct inode *inode, struct file *file); 17 | static int dom_chardev_release(struct inode *inode, struct file *file); 18 | static long dom_chardev_ioctl (struct file *file, unsigned int cmd, unsigned long arg); 19 | static ssize_t dom_chardev_read (struct file *file, char __user *buf, size_t count, loff_t *offset); 20 | static ssize_t dom_chardev_write (struct file *file, const char __user *buf, size_t count, loff_t *offset); 21 | 22 | // Create and populate a struct for the file operations 23 | static const struct file_operations dom_chardev_fops = { 24 | .owner = THIS_MODULE, 25 | .open = dom_chardev_open, 26 | .release = dom_chardev_release, 27 | .unlocked_ioctl = dom_chardev_ioctl, 28 | .read = dom_chardev_read, 29 | .write = dom_chardev_write 30 | }; 31 | 32 | // This creates a cdev struct 33 | struct dom_char_device_data { 34 | struct cdev dom_cdev; 35 | }; 36 | 37 | // Setting dev_major to 0 means dynamically allocate a new major device number for the module - whatever is free 38 | // This is a good practice to avoid conflicts with other modules and drivers 39 | static int dev_major = 0; 40 | 41 | // We don't require a class here. Set up as many devices that we wanted earlier with MAX_DEVICES 42 | static struct class *dom_chardev_class = NULL; 43 | static struct dom_char_device_data dom_chardev_data[MAX_DEVICES]; 44 | 45 | //This is for the uevent. From what I can tell, performing cat uevent gives info on the particular device 46 | static int dom_chardev_uevent(struct device *dev, struct kobj_uevent_env *env) 47 | { 48 | add_uevent_var(env, "DEVMODE=%#o", 0666); 49 | return 0; 50 | } 51 | 52 | // Initialization function. Only runs at initialization as seen with the __init. This is destroyed when module is loaded 53 | static int __init dom_chardev_init(void) 54 | { 55 | int err, i; //initialize err and i. err is not used later on. i is the iterator number 56 | dev_t dev; //define a new dev of the dev_t type 57 | 58 | // Allocate major and minor numbers for each device 59 | // Start at 0, go up to MAX_DEVICES, name domchardev 60 | err = alloc_chrdev_region(&dev, 0, MAX_DEVICES, "domchardev"); 61 | 62 | //Find the major number of the device using the MAJOR() macro 63 | dev_major = MAJOR(dev); 64 | 65 | // Create the class and add the uevent. Not quite sure what this does. 66 | dom_chardev_class = class_create(THIS_MODULE, "domchardev"); 67 | dom_chardev_class->dev_uevent = dom_chardev_uevent; 68 | 69 | // Run a for loop to create MAX_DEVICES number of devices 70 | for (i = 0; i < MAX_DEVICES; i++) { 71 | 72 | // The first option is the cdev from the struct for the particular device. Second option is 73 | // the file operations struct defined before 74 | cdev_init(&dom_chardev_data[i].dom_cdev, &dom_chardev_fops); 75 | 76 | // Set the owner to be THIS_MODULE on the device 77 | dom_chardev_data[i].dom_cdev.owner = THIS_MODULE; 78 | 79 | // Add the device to the system. The MKDEV macro makes a device with the major and minor numbers specified 80 | cdev_add(&dom_chardev_data[i].dom_cdev, MKDEV(dev_major, i), 1); 81 | 82 | // Create a device file node and register with sysfs 83 | device_create(dom_chardev_class, NULL, MKDEV(dev_major, i), NULL, "domchardev-%d", i); 84 | 85 | //print that devices have started 86 | printk("Successfully started DOMCHARDEV-(%d, %d)\n", dev_major, i); 87 | } 88 | 89 | return 0; 90 | } 91 | 92 | // Meant only for __exit when closing the driver 93 | static void __exit dom_chardev_exit(void) 94 | { 95 | int i; 96 | 97 | // Destroy the devices and print a message saying so 98 | for (i = 0; i < MAX_DEVICES; i++) { 99 | device_destroy(dom_chardev_class, MKDEV(dev_major, i)); 100 | //print that devices have started 101 | printk("Successfully destroyed DOMCHARDEV-(%d, %d)\n", dev_major, i); 102 | } 103 | 104 | // Unregister the class, then destroy it 105 | class_unregister(dom_chardev_class); 106 | class_destroy(dom_chardev_class); 107 | 108 | unregister_chrdev_region(MKDEV(dev_major, 0), MINORMASK); 109 | } 110 | 111 | static int dom_chardev_open(struct inode *inode, struct file *file) 112 | { 113 | // Simply print that the device has been opened 114 | printk("DOMCHARDEV-%d: Device open\n", MINOR(file->f_path.dentry->d_inode->i_rdev)); 115 | return 0; 116 | } 117 | 118 | static int dom_chardev_release(struct inode *inode, struct file *file) 119 | { 120 | // Simply print that the device has been closed 121 | printk("DOMCHARDEV-%d: Device close\n", MINOR(file->f_path.dentry->d_inode->i_rdev)); 122 | return 0; 123 | } 124 | 125 | static long dom_chardev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 126 | { 127 | // ioctl stuff 128 | printk("DOMCHARDEV-%d: Device ioctl\n", MINOR(file->f_path.dentry->d_inode->i_rdev)); 129 | return 0; 130 | } 131 | 132 | // read function for the fops struct 133 | static ssize_t dom_chardev_read(struct file *file, char __user *buf, size_t count, loff_t *offset) 134 | { 135 | uint8_t *data = "Hello from the kernel world! This is Dom's char device!\n"; 136 | size_t datalen = strlen(data); 137 | 138 | printk("Reading device number: (%d, %d)\n", dev_major, MINOR(file->f_path.dentry->d_inode->i_rdev)); 139 | 140 | // Saturate count to data length if needed 141 | if (count > datalen) { 142 | count = datalen; 143 | } 144 | 145 | // If the copy of data fails, return the EFault. The copy_to_user should also give the user the data 146 | if (copy_to_user(buf, data, count)) { 147 | return -EFAULT; 148 | } 149 | 150 | // This should return the number of bytes transferred to the read 151 | return count; 152 | } 153 | 154 | static ssize_t dom_chardev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) 155 | { 156 | //Check my counting logic here. I could be off 157 | size_t maxdatalen = 10; 158 | unsigned long ncopied; 159 | uint8_t databuf[10]; 160 | size_t overflow = 0; 161 | 162 | // Use this for debugging count stuff 163 | //printk("Size of count: %zd\n", count); 164 | 165 | printk("Writing device number: (%d, %d)\n", dev_major, MINOR(file->f_path.dentry->d_inode->i_rdev)); 166 | 167 | //truncate maxdatalen if the bytes to send is less than maxdatalen 168 | if (maxdatalen > count) { 169 | maxdatalen = count; 170 | } 171 | //Warn if too much data is trying to be written 172 | else if (maxdatalen < (count)){ 173 | overflow = count - maxdatalen; 174 | printk("Too big of an input. Unable to copy %ld byte(s) from the user\n", (overflow)); 175 | } 176 | 177 | ncopied = copy_from_user(databuf, buf, maxdatalen); 178 | 179 | //Print the number of copied bytes from the user 180 | printk("Copied %zd bytes from the user\n", maxdatalen); 181 | databuf[maxdatalen] = 0; 182 | 183 | //Print the copied bytes from the user 184 | printk("Data from the user: %s\n", databuf); 185 | 186 | return count; 187 | } 188 | 189 | module_init(dom_chardev_init); 190 | module_exit(dom_chardev_exit); 191 | 192 | MODULE_LICENSE("Dual MIT/GPL"); 193 | MODULE_AUTHOR("Dom"); 194 | -------------------------------------------------------------------------------- /Code_Examples/Hello_World/Makefile: -------------------------------------------------------------------------------- 1 | # If KERNELRELEASE is defined, we've been invoked from the 2 | # kernel build system and can use its language. 3 | ifneq ($(KERNELRELEASE),) 4 | obj-m := hello.o 5 | # Otherwise we were called directly from the command 6 | # line; invoke the kernel build system. 7 | else 8 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 9 | PWD := $(shell pwd) 10 | default: 11 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 12 | endif 13 | -------------------------------------------------------------------------------- /Code_Examples/Hello_World/README.md: -------------------------------------------------------------------------------- 1 | ### Your First Driver (have fun, get frustrated, break stuff, fix stuff) 2 | 3 | This is my version of the hello_world that you will see for just about every programming language. It is meant to introduce the concepts of compiling, loading, and viewing a kernel module in action. 4 | 5 | First, make sure you have the proper kernel source files on your machine: 6 | 7 | ```shell 8 | $ sudo apt install build-essential linux-headers-$(uname -r) 9 | ``` 10 | 11 | Next, put these files into a separate directory (can be wherever). You will need `hello.c` and `Makefile`. Next, login as root using: 12 | 13 | ```shell 14 | $ sudo -s 15 | ``` 16 | 17 | And then run: 18 | 19 | ```shell 20 | $ make 21 | ``` 22 | 23 | Your output may look similar to this: 24 | 25 | ```shell 26 | make -C /lib/modules/5.3.0-7648-generic/build M=/home/dom/LDD3-Notes/Code_Examples/Hello_World modules 27 | make[1]: Entering directory '/usr/src/linux-headers-5.3.0-7648-generic' 28 | CC [M] /home/dom/LDD3-Notes/Code_Examples/Hello_World/hello.o 29 | Building modules, stage 2. 30 | MODPOST 1 modules 31 | CC /home/dom/LDD3-Notes/Code_Examples/Hello_World/hello.mod.o 32 | LD [M] /home/dom/LDD3-Notes/Code_Examples/Hello_World/hello.ko 33 | make[1]: Leaving directory '/usr/src/linux-headers-5.3.0-7648-generic' 34 | ``` 35 | 36 | Running a simple ls -l reveals a lot of files! 37 | 38 | ```shell 39 | $ ls -l 40 | 41 | -rw-r--r-- 1 dom dom 2271 Feb 12 12:20 hello.c 42 | -rw-r--r-- 1 root root 7984 Apr 25 15:25 hello.ko 43 | -rw-r--r-- 1 root root 56 Apr 25 15:25 hello.mod 44 | -rw-r--r-- 1 root root 646 Apr 25 15:25 hello.mod.c 45 | -rw-r--r-- 1 root root 2800 Apr 25 15:25 hello.mod.o 46 | -rw-r--r-- 1 root root 6072 Apr 25 15:25 hello.o 47 | -rw-r--r-- 1 dom dom 378 Feb 12 12:20 Makefile 48 | -rw-r--r-- 1 root root 56 Apr 25 15:25 modules.order 49 | -rw-r--r-- 1 root root 0 Apr 25 15:25 Module.symvers 50 | ``` 51 | 52 | The one we are interested in now is called `hello.ko`. This is our kernel object. Now we can load it into the kernel with: 53 | 54 | ```shell 55 | $ insmod hello.ko 56 | ``` 57 | 58 | Now, in another terminal, we can look at the output of the module to the kernel log with: 59 | 60 | ```shell 61 | $ dmesg -wH 62 | 63 | [Apr25 17:27] Hello, world 64 | ============= 65 | [ +0.000004] short integer: 1 66 | [ +0.000002] integer: 56 67 | [ +0.000002] long integer: 1900 68 | [ +0.000002] string: test string 69 | [ +0.000002] intArray[0] = 1 70 | [ +0.000001] intArray[1] = 2 71 | [ +0.000002] intArray[2] = 3 72 | [ +0.000001] intArray[3] = 4 73 | [ +0.000002] intArray[4] = 5 74 | [ +0.000001] intArray[5] = -8 75 | [ +0.000002] got 0 arguments for intArray. 76 | ``` 77 | 78 | The module can be removed with: 79 | 80 | ```shell 81 | $ rmmod hello 82 | ``` 83 | 84 | And the resulting output in dmesg will look like: 85 | 86 | ```shell 87 | [Apr25 18:14] Goodbye, cruel world! 88 | ``` 89 | 90 | Now for some fun - passing command line arguments to a module: 91 | 92 | ```shell 93 | $ insmod hello.ko short_int=4 reg_int=5 long_int=56789 sample_string="The_answer_is_42" intArray=9,9,9 94 | ``` 95 | 96 | 97 | ```shell 98 | [ +5.091416] Hello, world 99 | ============= 100 | [ +0.000004] short integer: 4 101 | [ +0.000002] integer: 5 102 | [ +0.000002] long integer: 56789 103 | [ +0.000002] string: The_answer_is_42 104 | [ +0.000002] intArray[0] = 9 105 | [ +0.000002] intArray[1] = 9 106 | [ +0.000001] intArray[2] = 9 107 | [ +0.000002] intArray[3] = 4 108 | [ +0.000002] intArray[4] = 5 109 | [ +0.000002] intArray[5] = -8 110 | [ +0.000002] got 3 arguments for intArray. 111 | ``` 112 | -------------------------------------------------------------------------------- /Code_Examples/Hello_World/hello.c: -------------------------------------------------------------------------------- 1 | // Hello.c file demonstartes command line argument passing with the kernel 2 | 3 | // Start by including the appropriate header files 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // Give it some sort of license and author so that the kernel does not complain 11 | MODULE_LICENSE("GPL"); 12 | MODULE_AUTHOR("DSR"); 13 | 14 | // Lets initialize some variables of a bunch of different types to play with 15 | static short int short_int = 1; 16 | static int reg_int = 56; 17 | static long int long_int = 1900; 18 | static char *sample_string = "test string"; 19 | static int intArray[6] = {1,2,3,4,5,-8}; 20 | static int arr_argc = 0; 21 | 22 | 23 | /* This part introduces command line parameter passing 24 | * module_param(foo, int, 0000) 25 | * The first param is the parameters name 26 | * The second param is it's data type 27 | * The final argument is the permissions bits, 28 | * for exposing parameters in sysfs (if non-zero) at a later stage. 29 | */ 30 | module_param(short_int, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 31 | MODULE_PARM_DESC(short_int, "A short integer example"); 32 | module_param(reg_int, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 33 | MODULE_PARM_DESC(reg_int, "A normal integer example"); 34 | module_param(long_int, long, S_IRUSR); 35 | MODULE_PARM_DESC(long_int, "A long integer example"); 36 | module_param(sample_string, charp, 0000); 37 | MODULE_PARM_DESC(sample_string, "A character string example"); 38 | 39 | /* There is a slightly different setup for passing an array of parameters 40 | * module_param_array(name, type, num, perm); 41 | * The first param is the parameter's (in this case the array's) name 42 | * The second param is the data type of the elements of the array 43 | * The third argument is a pointer to the variable that will store the number 44 | * of elements of the array initialized by the user at module loading time 45 | * The fourth argument is the permission bits 46 | */ 47 | module_param_array(intArray, int, &arr_argc, 0000); 48 | MODULE_PARM_DESC(intArray, "An array of integers"); 49 | 50 | static int __init hello_init(void) 51 | { 52 | int i; 53 | printk(KERN_INFO "Hello, world \n============= \n"); 54 | printk(KERN_INFO "short integer: %hd\n", short_int); 55 | printk(KERN_INFO "integer: %d\n", reg_int); 56 | printk(KERN_INFO "long integer: %ld\n", long_int); 57 | printk(KERN_INFO "string: %s\n", sample_string); 58 | for (i = 0; i < (sizeof intArray / sizeof (int)); i++) 59 | { 60 | printk(KERN_INFO "intArray[%d] = %d\n", i, intArray[i]); 61 | } 62 | printk(KERN_INFO "got %d arguments for intArray.\n", arr_argc); 63 | return 0; 64 | } 65 | 66 | static void __exit hello_exit(void) 67 | { 68 | printk(KERN_INFO "Goodbye, cruel world!\n"); 69 | } 70 | 71 | module_init(hello_init); 72 | module_exit(hello_exit); 73 | -------------------------------------------------------------------------------- /Code_Examples/Net_Driver/Makefile: -------------------------------------------------------------------------------- 1 | MODULE_NAME := domnetfilter 2 | obj-m := $(MODULE_NAME).o 3 | 4 | OBJ_LIST := filter.o 5 | $(MODULE_NAME)-y += $(OBJ_LIST) 6 | 7 | ccflags-y := -O2 8 | 9 | KERNELDIR := /lib/modules/$(shell uname -r)/build 10 | 11 | all: filter 12 | 13 | filter: 14 | make -C $(KERNELDIR) M=$(PWD) modules 15 | -------------------------------------------------------------------------------- /Code_Examples/Net_Driver/README.md: -------------------------------------------------------------------------------- 1 | # Networking Fun 2 | #### No, not the kind where you have to meet a lot of people 3 | 4 | If you want to be really mean to one of your roomates - here is a way to disable all TCP connections on a computer at the kernel level. Start by downloading the two source files, running `make` and inserting the module into the kernel. The module has one input parameter that will enable/disable TCP blocking. First, let's do the normal case: 5 | 6 | ```shell 7 | $ insmod domnetfilter.ko 8 | ``` 9 | 10 | With corresponding output in dmesg as: 11 | 12 | ```shell 13 | [Apr26 19:22] domnetfilter: Doms Network Filter Started! 14 | [ +0.000004] domnetfilter: Major number 510 15 | [ +13.188771] domnetfilter: TCP connection initiated from 192.168.1.XXX:XXXXX 16 | [ +0.000003] domnetfilter: Packets allowed to pass! 17 | ``` 18 | 19 | - I replaced the exact IP address with X's to denote that these will be different for your machine 20 | - Notice: the module says "Packets allowed to pass!" 21 | - Blocking has not been enabled yet 22 | 23 | Next, we are going to have some fun. To block all TCP, run the module with the following input: 24 | 25 | ```shell 26 | insmod domnetfilter.ko toggle_string="block" 27 | ``` 28 | 29 | Now you will see the following in dmesg: 30 | 31 | ```shell 32 | [ +0.447914] domnetfilter: TCP connection initiated from 192.168.1.XXX:XXXXX 33 | [ +0.000047] domnetfilter: Packets being blocked! 34 | ``` 35 | 36 | Try and browse the web. Nothing should happen. You will need to run the module again without the blocking flag set to restore TCP packets being delivered. 37 | 38 | Have fun, and don't use this for (pure) evil. 39 | -------------------------------------------------------------------------------- /Code_Examples/Net_Driver/filter.c: -------------------------------------------------------------------------------- 1 | // Kernel module that blocks/allows tcp connections 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #define IOCTL_FILTER_ADDRESS _IOW('k', 1, unsigned int) // Used for creating the ioctl command number 23 | 24 | static char *toggle_string = "no_block"; 25 | module_param(toggle_string, charp, 0000); 26 | MODULE_PARM_DESC(toggle_string, "Toggle Blocker on/off"); 27 | 28 | static int dom_netfilter_open(struct inode *inode, struct file *file); 29 | static int dom_netfilter_release(struct inode *inode, struct file *file); 30 | static long dom_netfilter_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 31 | 32 | static const struct file_operations fops = { 33 | .owner = THIS_MODULE, 34 | .open = dom_netfilter_open, 35 | .release = dom_netfilter_release, 36 | .unlocked_ioctl = dom_netfilter_ioctl 37 | }; 38 | 39 | static unsigned int dom_netfilter_hookfn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state); 40 | 41 | static struct nf_hook_ops net_nfho = { 42 | .hook = dom_netfilter_hookfn, 43 | .hooknum = NF_INET_LOCAL_OUT, 44 | .pf = PF_INET, 45 | .priority = NF_IP_PRI_FIRST 46 | }; 47 | 48 | static struct cdev dom_cdev; 49 | static int dev_major = 0; 50 | static atomic_t ioctl_set; 51 | static unsigned int ioctl_set_addr; 52 | 53 | // Test ioctl_set_addr if it has been set. 54 | static int test_daddr(unsigned int dst_addr) { 55 | int ret = 0; 56 | 57 | if (atomic_read(&ioctl_set) == 1) 58 | ret = (ioctl_set_addr == dst_addr); 59 | else 60 | ret = 1; 61 | 62 | return ret; 63 | } 64 | 65 | static unsigned int dom_netfilter_hookfn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { 66 | // get IP header 67 | struct iphdr *iph = ip_hdr(skb); 68 | 69 | if (iph->protocol == IPPROTO_TCP && test_daddr(iph->daddr)) { 70 | // then get the TCP header 71 | struct tcphdr *tcph = tcp_hdr(skb); 72 | 73 | // see if the packet was for initiation 74 | if (tcph->syn && !tcph->ack) { 75 | printk("domnetfilter: TCP connection initiated from " "%pI4:%u\n", &iph->saddr, ntohs(tcph->source)); 76 | if (!strcmp(toggle_string, "block")) 77 | printk("domnetfilter: Packets being blocked!"); 78 | else 79 | printk("domnetfilter: Packets allowed to pass!"); 80 | } 81 | } 82 | 83 | // what to do with the packets... 84 | if (!strcmp(toggle_string, "block")) 85 | return NF_DROP; 86 | else 87 | return NF_ACCEPT; 88 | } 89 | 90 | static int dom_netfilter_open(struct inode *inode, struct file *file) { 91 | return 0; 92 | } 93 | 94 | static int dom_netfilter_release(struct inode *inode, struct file *file) { 95 | return 0; 96 | } 97 | 98 | static long dom_netfilter_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { 99 | switch (cmd) { 100 | case IOCTL_FILTER_ADDRESS: 101 | if (copy_from_user(&ioctl_set_addr, (void *) arg, sizeof(ioctl_set_addr))) 102 | return -EFAULT; 103 | atomic_set(&ioctl_set, 1); 104 | break; 105 | 106 | default: 107 | return -ENOTTY; //indicates ioctl is not setup properly 108 | } 109 | 110 | return 0; 111 | } 112 | 113 | int __init domnet_init(void) { 114 | int err; 115 | dev_t dev; 116 | err = alloc_chrdev_region(&dev, 0, 1, "domnetfilter"); 117 | 118 | //Find the major number of the device using the MAJOR() macro 119 | dev_major = MAJOR(dev); 120 | printk("domnetfilter: Doms Network Filter Started!"); 121 | printk("domnetfilter: Major number %d", dev_major); 122 | 123 | atomic_set(&ioctl_set, 0); 124 | ioctl_set_addr = 0; 125 | 126 | cdev_init(&dom_cdev, &fops); 127 | cdev_add(&dom_cdev, MKDEV(dev_major, 0), 1); 128 | 129 | err = nf_register_net_hook(&init_net, &net_nfho); 130 | 131 | if (err) 132 | goto out; 133 | 134 | return 0; 135 | 136 | out: 137 | // cleanup the device if init not successful 138 | printk("domnetfilter: Doms Network Filter Destroyed!"); 139 | cdev_del(&dom_cdev); 140 | unregister_chrdev_region(MKDEV(dev_major, 0), 1); 141 | return err; 142 | } 143 | 144 | void __exit domnet_exit(void) { 145 | printk("domnetfilter: Doms Network Filter Destroyed!"); 146 | nf_unregister_net_hook(&init_net, &net_nfho); 147 | cdev_del(&dom_cdev); 148 | unregister_chrdev_region(MKDEV(dev_major, 0), 1); 149 | } 150 | 151 | module_init(domnet_init); 152 | module_exit(domnet_exit); 153 | 154 | MODULE_DESCRIPTION("TCP netfilter module"); 155 | MODULE_AUTHOR("Dom"); 156 | MODULE_LICENSE("GPL"); 157 | -------------------------------------------------------------------------------- /Code_Examples/README.md: -------------------------------------------------------------------------------- 1 | # Code Examples for LDD3 Notes 2 | 3 | ### What You Will Find Here 4 | 5 | The examples you see here are ones that I had to create/modify that you probably won't be able to find an exact version of on someone else's repo. 6 | 7 | ### Other Good Repos 8 | 9 | There appears to be a few people maintaining their own versions of the original LDD3 examples. Here are links to two really good repos to look at for the book examples: 10 | 11 | - [Javier Martinez Canillas LDD3](https://github.com/martinezjavier/ldd3) 12 | - [CU Boulder Fork of the Previous Repo](https://github.com/cu-ecen-5013/ldd3) (this one can sometimes work better) 13 | 14 | ### How to Use These Files 15 | 16 | I am currently using kernel 5.3.0-7648 to run these examples. Each individual example should have its own readme. In general, you should just have to run make in the main directory. 17 | -------------------------------------------------------------------------------- /Code_Examples/scull/Makefile: -------------------------------------------------------------------------------- 1 | # Comment/uncomment the following line to disable/enable debugging 2 | #DEBUG = y 3 | 4 | 5 | # Add your debugging flag (or not) to CFLAGS 6 | ifeq ($(DEBUG),y) 7 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 8 | else 9 | DEBFLAGS = -O2 10 | endif 11 | 12 | LDDINC=$(PWD)/../include 13 | 14 | EXTRA_CFLAGS += $(DEBFLAGS) 15 | EXTRA_CFLAGS += -I$(LDDINC) 16 | 17 | ifneq ($(KERNELRELEASE),) 18 | # call from kernel build system 19 | 20 | scull-objs := main.o pipe.o access.o 21 | 22 | obj-m := scull.o 23 | 24 | else 25 | 26 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 27 | PWD := $(shell pwd) 28 | 29 | modules: 30 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 31 | 32 | endif 33 | 34 | 35 | 36 | clean: 37 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions 38 | 39 | depend .depend dep: 40 | $(CC) $(EXTRA_CFLAGS) -M *.c > .depend 41 | 42 | 43 | ifeq (.depend,$(wildcard .depend)) 44 | include .depend 45 | endif 46 | -------------------------------------------------------------------------------- /Code_Examples/scull/Module.symvers: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropellad/LDD3-Notes/c9a39592a7cd4b162c8d77e5a1f011f7452939df/Code_Examples/scull/Module.symvers -------------------------------------------------------------------------------- /Code_Examples/scull/README.md: -------------------------------------------------------------------------------- 1 | # Scull :skull: 2 | 3 | This functions the same as the book describes. See the book chapters for more notes on how to play around with this driver. I have not made any changes to it. 4 | -------------------------------------------------------------------------------- /Code_Examples/scull/access.c: -------------------------------------------------------------------------------- 1 | /* 2 | * access.c -- the files with access control on open 3 | * 4 | * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet 5 | * Copyright (C) 2001 O'Reilly & Associates 6 | * 7 | * The source code in this file can be freely used, adapted, 8 | * and redistributed in source or binary form, so long as an 9 | * acknowledgment appears in derived source files. The citation 10 | * should list that the code comes from the book "Linux Device 11 | * Drivers" by Alessandro Rubini and Jonathan Corbet, published 12 | * by O'Reilly & Associates. No warranty is attached; 13 | * we cannot take responsibility for errors or fitness for use. 14 | * 15 | * $Id: access.c,v 1.17 2004/09/26 07:29:56 gregkh Exp $ 16 | */ 17 | 18 | /* FIXME: cloned devices as a use for kobjects? */ 19 | 20 | #include /* printk() */ 21 | #include 22 | #include /* kmalloc() */ 23 | #include /* everything... */ 24 | #include /* error codes */ 25 | #include /* size_t */ 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include /* current_uid(), current_euid() */ 32 | #include 33 | #include 34 | 35 | #include "scull.h" /* local definitions */ 36 | 37 | static dev_t scull_a_firstdev; /* Where our range begins */ 38 | 39 | /* 40 | * These devices fall back on the main scull operations. They only 41 | * differ in the implementation of open() and close() 42 | */ 43 | 44 | 45 | 46 | /************************************************************************ 47 | * 48 | * The first device is the single-open one, 49 | * it has an hw structure and an open count 50 | */ 51 | 52 | static struct scull_dev scull_s_device; 53 | static atomic_t scull_s_available = ATOMIC_INIT(1); 54 | 55 | static int scull_s_open(struct inode *inode, struct file *filp) 56 | { 57 | struct scull_dev *dev = &scull_s_device; /* device information */ 58 | 59 | if (! atomic_dec_and_test (&scull_s_available)) { 60 | atomic_inc(&scull_s_available); 61 | return -EBUSY; /* already open */ 62 | } 63 | 64 | /* then, everything else is copied from the bare scull device */ 65 | if ( (filp->f_flags & O_ACCMODE) == O_WRONLY) 66 | scull_trim(dev); 67 | filp->private_data = dev; 68 | return 0; /* success */ 69 | } 70 | 71 | static int scull_s_release(struct inode *inode, struct file *filp) 72 | { 73 | atomic_inc(&scull_s_available); /* release the device */ 74 | return 0; 75 | } 76 | 77 | 78 | /* 79 | * The other operations for the single-open device come from the bare device 80 | */ 81 | struct file_operations scull_sngl_fops = { 82 | .owner = THIS_MODULE, 83 | .llseek = scull_llseek, 84 | .read = scull_read, 85 | .write = scull_write, 86 | .unlocked_ioctl = scull_ioctl, 87 | .open = scull_s_open, 88 | .release = scull_s_release, 89 | }; 90 | 91 | 92 | /************************************************************************ 93 | * 94 | * Next, the "uid" device. It can be opened multiple times by the 95 | * same user, but access is denied to other users if the device is open 96 | */ 97 | 98 | static struct scull_dev scull_u_device; 99 | static int scull_u_count; /* initialized to 0 by default */ 100 | static uid_t scull_u_owner; /* initialized to 0 by default */ 101 | static DEFINE_SPINLOCK(scull_u_lock); 102 | 103 | static int scull_u_open(struct inode *inode, struct file *filp) 104 | { 105 | struct scull_dev *dev = &scull_u_device; /* device information */ 106 | 107 | spin_lock(&scull_u_lock); 108 | if (scull_u_count && 109 | (scull_u_owner != current_uid().val) && /* allow user */ 110 | (scull_u_owner != current_euid().val) && /* allow whoever did su */ 111 | !capable(CAP_DAC_OVERRIDE)) { /* still allow root */ 112 | spin_unlock(&scull_u_lock); 113 | return -EBUSY; /* -EPERM would confuse the user */ 114 | } 115 | 116 | if (scull_u_count == 0) 117 | scull_u_owner = current_uid().val; /* grab it */ 118 | 119 | scull_u_count++; 120 | spin_unlock(&scull_u_lock); 121 | 122 | /* then, everything else is copied from the bare scull device */ 123 | 124 | if ((filp->f_flags & O_ACCMODE) == O_WRONLY) 125 | scull_trim(dev); 126 | filp->private_data = dev; 127 | return 0; /* success */ 128 | } 129 | 130 | static int scull_u_release(struct inode *inode, struct file *filp) 131 | { 132 | spin_lock(&scull_u_lock); 133 | scull_u_count--; /* nothing else */ 134 | spin_unlock(&scull_u_lock); 135 | return 0; 136 | } 137 | 138 | 139 | 140 | /* 141 | * The other operations for the device come from the bare device 142 | */ 143 | struct file_operations scull_user_fops = { 144 | .owner = THIS_MODULE, 145 | .llseek = scull_llseek, 146 | .read = scull_read, 147 | .write = scull_write, 148 | .unlocked_ioctl = scull_ioctl, 149 | .open = scull_u_open, 150 | .release = scull_u_release, 151 | }; 152 | 153 | 154 | /************************************************************************ 155 | * 156 | * Next, the device with blocking-open based on uid 157 | */ 158 | 159 | static struct scull_dev scull_w_device; 160 | static int scull_w_count; /* initialized to 0 by default */ 161 | static uid_t scull_w_owner; /* initialized to 0 by default */ 162 | static DECLARE_WAIT_QUEUE_HEAD(scull_w_wait); 163 | static DEFINE_SPINLOCK(scull_w_lock); 164 | 165 | static inline int scull_w_available(void) 166 | { 167 | return scull_w_count == 0 || 168 | scull_w_owner == current_uid().val || 169 | scull_w_owner == current_euid().val || 170 | capable(CAP_DAC_OVERRIDE); 171 | } 172 | 173 | 174 | static int scull_w_open(struct inode *inode, struct file *filp) 175 | { 176 | struct scull_dev *dev = &scull_w_device; /* device information */ 177 | 178 | spin_lock(&scull_w_lock); 179 | while (! scull_w_available()) { 180 | spin_unlock(&scull_w_lock); 181 | if (filp->f_flags & O_NONBLOCK) return -EAGAIN; 182 | if (wait_event_interruptible (scull_w_wait, scull_w_available())) 183 | return -ERESTARTSYS; /* tell the fs layer to handle it */ 184 | spin_lock(&scull_w_lock); 185 | } 186 | if (scull_w_count == 0) 187 | scull_w_owner = current_uid().val; /* grab it */ 188 | scull_w_count++; 189 | spin_unlock(&scull_w_lock); 190 | 191 | /* then, everything else is copied from the bare scull device */ 192 | if ((filp->f_flags & O_ACCMODE) == O_WRONLY) 193 | scull_trim(dev); 194 | filp->private_data = dev; 195 | return 0; /* success */ 196 | } 197 | 198 | static int scull_w_release(struct inode *inode, struct file *filp) 199 | { 200 | int temp; 201 | 202 | spin_lock(&scull_w_lock); 203 | scull_w_count--; 204 | temp = scull_w_count; 205 | spin_unlock(&scull_w_lock); 206 | 207 | if (temp == 0) 208 | wake_up_interruptible_sync(&scull_w_wait); /* awake other uid's */ 209 | return 0; 210 | } 211 | 212 | 213 | /* 214 | * The other operations for the device come from the bare device 215 | */ 216 | struct file_operations scull_wusr_fops = { 217 | .owner = THIS_MODULE, 218 | .llseek = scull_llseek, 219 | .read = scull_read, 220 | .write = scull_write, 221 | .unlocked_ioctl = scull_ioctl, 222 | .open = scull_w_open, 223 | .release = scull_w_release, 224 | }; 225 | 226 | /************************************************************************ 227 | * 228 | * Finally the `cloned' private device. This is trickier because it 229 | * involves list management, and dynamic allocation. 230 | */ 231 | 232 | /* The clone-specific data structure includes a key field */ 233 | 234 | struct scull_listitem { 235 | struct scull_dev device; 236 | dev_t key; 237 | struct list_head list; 238 | 239 | }; 240 | 241 | /* The list of devices, and a lock to protect it */ 242 | static LIST_HEAD(scull_c_list); 243 | static DEFINE_SPINLOCK(scull_c_lock); 244 | 245 | /* A placeholder scull_dev which really just holds the cdev stuff. */ 246 | static struct scull_dev scull_c_device; 247 | 248 | /* Look for a device or create one if missing */ 249 | static struct scull_dev *scull_c_lookfor_device(dev_t key) 250 | { 251 | struct scull_listitem *lptr; 252 | 253 | list_for_each_entry(lptr, &scull_c_list, list) { 254 | if (lptr->key == key) 255 | return &(lptr->device); 256 | } 257 | 258 | /* not found */ 259 | lptr = kmalloc(sizeof(struct scull_listitem), GFP_KERNEL); 260 | if (!lptr) 261 | return NULL; 262 | 263 | /* initialize the device */ 264 | memset(lptr, 0, sizeof(struct scull_listitem)); 265 | lptr->key = key; 266 | scull_trim(&(lptr->device)); /* initialize it */ 267 | mutex_init(&lptr->device.lock); 268 | 269 | /* place it in the list */ 270 | list_add(&lptr->list, &scull_c_list); 271 | 272 | return &(lptr->device); 273 | } 274 | 275 | static int scull_c_open(struct inode *inode, struct file *filp) 276 | { 277 | struct scull_dev *dev; 278 | dev_t key; 279 | 280 | if (!current->signal->tty) { 281 | PDEBUG("Process \"%s\" has no ctl tty\n", current->comm); 282 | return -EINVAL; 283 | } 284 | key = tty_devnum(current->signal->tty); 285 | 286 | /* look for a scullc device in the list */ 287 | spin_lock(&scull_c_lock); 288 | dev = scull_c_lookfor_device(key); 289 | spin_unlock(&scull_c_lock); 290 | 291 | if (!dev) 292 | return -ENOMEM; 293 | 294 | /* then, everything else is copied from the bare scull device */ 295 | if ( (filp->f_flags & O_ACCMODE) == O_WRONLY) 296 | scull_trim(dev); 297 | filp->private_data = dev; 298 | return 0; /* success */ 299 | } 300 | 301 | static int scull_c_release(struct inode *inode, struct file *filp) 302 | { 303 | /* 304 | * Nothing to do, because the device is persistent. 305 | * A `real' cloned device should be freed on last close 306 | */ 307 | return 0; 308 | } 309 | 310 | 311 | 312 | /* 313 | * The other operations for the device come from the bare device 314 | */ 315 | struct file_operations scull_priv_fops = { 316 | .owner = THIS_MODULE, 317 | .llseek = scull_llseek, 318 | .read = scull_read, 319 | .write = scull_write, 320 | .unlocked_ioctl = scull_ioctl, 321 | .open = scull_c_open, 322 | .release = scull_c_release, 323 | }; 324 | 325 | /************************************************************************ 326 | * 327 | * And the init and cleanup functions come last 328 | */ 329 | 330 | static struct scull_adev_info { 331 | char *name; 332 | struct scull_dev *sculldev; 333 | struct file_operations *fops; 334 | } scull_access_devs[] = { 335 | { "scullsingle", &scull_s_device, &scull_sngl_fops }, 336 | { "sculluid", &scull_u_device, &scull_user_fops }, 337 | { "scullwuid", &scull_w_device, &scull_wusr_fops }, 338 | { "scullpriv", &scull_c_device, &scull_priv_fops } 339 | }; 340 | #define SCULL_N_ADEVS 4 341 | 342 | /* 343 | * Set up a single device. 344 | */ 345 | static void scull_access_setup (dev_t devno, struct scull_adev_info *devinfo) 346 | { 347 | struct scull_dev *dev = devinfo->sculldev; 348 | int err; 349 | 350 | /* Initialize the device structure */ 351 | dev->quantum = scull_quantum; 352 | dev->qset = scull_qset; 353 | mutex_init(&dev->lock); 354 | 355 | /* Do the cdev stuff. */ 356 | cdev_init(&dev->cdev, devinfo->fops); 357 | kobject_set_name(&dev->cdev.kobj, devinfo->name); 358 | dev->cdev.owner = THIS_MODULE; 359 | err = cdev_add (&dev->cdev, devno, 1); 360 | /* Fail gracefully if need be */ 361 | if (err) { 362 | printk(KERN_NOTICE "Error %d adding %s\n", err, devinfo->name); 363 | kobject_put(&dev->cdev.kobj); 364 | } else 365 | printk(KERN_NOTICE "%s registered at %x\n", devinfo->name, devno); 366 | } 367 | 368 | 369 | int scull_access_init(dev_t firstdev) 370 | { 371 | int result, i; 372 | 373 | /* Get our number space */ 374 | result = register_chrdev_region (firstdev, SCULL_N_ADEVS, "sculla"); 375 | if (result < 0) { 376 | printk(KERN_WARNING "sculla: device number registration failed\n"); 377 | return 0; 378 | } 379 | scull_a_firstdev = firstdev; 380 | 381 | /* Set up each device. */ 382 | for (i = 0; i < SCULL_N_ADEVS; i++) 383 | scull_access_setup (firstdev + i, scull_access_devs + i); 384 | return SCULL_N_ADEVS; 385 | } 386 | 387 | /* 388 | * This is called by cleanup_module or on failure. 389 | * It is required to never fail, even if nothing was initialized first 390 | */ 391 | void scull_access_cleanup(void) 392 | { 393 | struct scull_listitem *lptr, *next; 394 | int i; 395 | 396 | /* Clean up the static devs */ 397 | for (i = 0; i < SCULL_N_ADEVS; i++) { 398 | struct scull_dev *dev = scull_access_devs[i].sculldev; 399 | cdev_del(&dev->cdev); 400 | scull_trim(scull_access_devs[i].sculldev); 401 | } 402 | 403 | /* And all the cloned devices */ 404 | list_for_each_entry_safe(lptr, next, &scull_c_list, list) { 405 | list_del(&lptr->list); 406 | scull_trim(&(lptr->device)); 407 | kfree(lptr); 408 | } 409 | 410 | /* Free up our number space */ 411 | unregister_chrdev_region(scull_a_firstdev, SCULL_N_ADEVS); 412 | return; 413 | } 414 | -------------------------------------------------------------------------------- /Code_Examples/scull/access_ok_version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @file access_ok_version.h 3 | * @date 10/13/2019 4 | * 5 | */ 6 | 7 | #include 8 | 9 | #if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0) 10 | #define access_ok_wrapper(type,arg,cmd) \ 11 | access_ok(type, arg, cmd) 12 | #else 13 | #define access_ok_wrapper(type,arg,cmd) \ 14 | access_ok(arg, cmd) 15 | #endif 16 | -------------------------------------------------------------------------------- /Code_Examples/scull/lddbus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Definitions for the virtual LDD bus. 3 | * 4 | * $Id: lddbus.h,v 1.4 2004/08/20 18:49:44 corbet Exp $ 5 | */ 6 | 7 | //extern struct device ldd_bus; 8 | extern struct bus_type ldd_bus_type; 9 | 10 | 11 | /* 12 | * The LDD driver type. 13 | */ 14 | 15 | struct ldd_driver { 16 | char *version; 17 | struct module *module; 18 | struct device_driver driver; 19 | struct driver_attribute version_attr; 20 | }; 21 | 22 | #define to_ldd_driver(drv) container_of(drv, struct ldd_driver, driver); 23 | 24 | /* 25 | * A device type for things "plugged" into the LDD bus. 26 | */ 27 | 28 | struct ldd_device { 29 | char *name; 30 | struct ldd_driver *driver; 31 | struct device dev; 32 | }; 33 | 34 | #define to_ldd_device(dev) container_of(dev, struct ldd_device, dev); 35 | 36 | extern int register_ldd_device(struct ldd_device *); 37 | extern void unregister_ldd_device(struct ldd_device *); 38 | extern int register_ldd_driver(struct ldd_driver *); 39 | extern void unregister_ldd_driver(struct ldd_driver *); 40 | -------------------------------------------------------------------------------- /Code_Examples/scull/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c -- the bare scull char module 3 | * 4 | * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet 5 | * Copyright (C) 2001 O'Reilly & Associates 6 | * 7 | * The source code in this file can be freely used, adapted, 8 | * and redistributed in source or binary form, so long as an 9 | * acknowledgment appears in derived source files. The citation 10 | * should list that the code comes from the book "Linux Device 11 | * Drivers" by Alessandro Rubini and Jonathan Corbet, published 12 | * by O'Reilly & Associates. No warranty is attached; 13 | * we cannot take responsibility for errors or fitness for use. 14 | * 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include /* printk() */ 22 | #include /* kmalloc() */ 23 | #include /* everything... */ 24 | #include /* error codes */ 25 | #include /* size_t */ 26 | #include 27 | #include /* O_ACCMODE */ 28 | #include 29 | #include 30 | 31 | #include /* copy_*_user */ 32 | 33 | #include "scull.h" /* local definitions */ 34 | #include "access_ok_version.h" 35 | 36 | /* 37 | * Our parameters which can be set at load time. 38 | */ 39 | 40 | int scull_major = SCULL_MAJOR; 41 | int scull_minor = 0; 42 | int scull_nr_devs = SCULL_NR_DEVS; /* number of bare scull devices */ 43 | int scull_quantum = SCULL_QUANTUM; 44 | int scull_qset = SCULL_QSET; 45 | 46 | module_param(scull_major, int, S_IRUGO); 47 | module_param(scull_minor, int, S_IRUGO); 48 | module_param(scull_nr_devs, int, S_IRUGO); 49 | module_param(scull_quantum, int, S_IRUGO); 50 | module_param(scull_qset, int, S_IRUGO); 51 | 52 | MODULE_AUTHOR("Alessandro Rubini, Jonathan Corbet"); 53 | MODULE_LICENSE("Dual BSD/GPL"); 54 | 55 | struct scull_dev *scull_devices; /* allocated in scull_init_module */ 56 | 57 | 58 | /* 59 | * Empty out the scull device; must be called with the device 60 | * semaphore held. 61 | */ 62 | int scull_trim(struct scull_dev *dev) 63 | { 64 | struct scull_qset *next, *dptr; 65 | int qset = dev->qset; /* "dev" is not-null */ 66 | int i; 67 | 68 | for (dptr = dev->data; dptr; dptr = next) { /* all the list items */ 69 | if (dptr->data) { 70 | for (i = 0; i < qset; i++) 71 | kfree(dptr->data[i]); 72 | kfree(dptr->data); 73 | dptr->data = NULL; 74 | } 75 | next = dptr->next; 76 | kfree(dptr); 77 | } 78 | dev->size = 0; 79 | dev->quantum = scull_quantum; 80 | dev->qset = scull_qset; 81 | dev->data = NULL; 82 | return 0; 83 | } 84 | #ifdef SCULL_DEBUG /* use proc only if debugging */ 85 | /* 86 | * The proc filesystem: function to read and entry 87 | */ 88 | 89 | int scull_read_procmem(struct seq_file *s, void *v) 90 | { 91 | int i, j; 92 | int limit = s->size - 80; /* Don't print more than this */ 93 | 94 | for (i = 0; i < scull_nr_devs && s->count <= limit; i++) { 95 | struct scull_dev *d = &scull_devices[i]; 96 | struct scull_qset *qs = d->data; 97 | if (mutex_lock_interruptible(&d->lock)) 98 | return -ERESTARTSYS; 99 | seq_printf(s,"\nDevice %i: qset %i, q %i, sz %li\n", 100 | i, d->qset, d->quantum, d->size); 101 | for (; qs && s->count <= limit; qs = qs->next) { /* scan the list */ 102 | seq_printf(s, " item at %p, qset at %p\n", 103 | qs, qs->data); 104 | if (qs->data && !qs->next) /* dump only the last item */ 105 | for (j = 0; j < d->qset; j++) { 106 | if (qs->data[j]) 107 | seq_printf(s, " % 4i: %8p\n", 108 | j, qs->data[j]); 109 | } 110 | } 111 | mutex_unlock(&scull_devices[i].lock); 112 | } 113 | return 0; 114 | } 115 | 116 | 117 | 118 | /* 119 | * Here are our sequence iteration methods. Our "position" is 120 | * simply the device number. 121 | */ 122 | static void *scull_seq_start(struct seq_file *s, loff_t *pos) 123 | { 124 | if (*pos >= scull_nr_devs) 125 | return NULL; /* No more to read */ 126 | return scull_devices + *pos; 127 | } 128 | 129 | static void *scull_seq_next(struct seq_file *s, void *v, loff_t *pos) 130 | { 131 | (*pos)++; 132 | if (*pos >= scull_nr_devs) 133 | return NULL; 134 | return scull_devices + *pos; 135 | } 136 | 137 | static void scull_seq_stop(struct seq_file *s, void *v) 138 | { 139 | /* Actually, there's nothing to do here */ 140 | } 141 | 142 | static int scull_seq_show(struct seq_file *s, void *v) 143 | { 144 | struct scull_dev *dev = (struct scull_dev *) v; 145 | struct scull_qset *d; 146 | int i; 147 | 148 | if (mutex_lock_interruptible(&dev->lock)) 149 | return -ERESTARTSYS; 150 | seq_printf(s, "\nDevice %i: qset %i, q %i, sz %li\n", 151 | (int) (dev - scull_devices), dev->qset, 152 | dev->quantum, dev->size); 153 | for (d = dev->data; d; d = d->next) { /* scan the list */ 154 | seq_printf(s, " item at %p, qset at %p\n", d, d->data); 155 | if (d->data && !d->next) /* dump only the last item */ 156 | for (i = 0; i < dev->qset; i++) { 157 | if (d->data[i]) 158 | seq_printf(s, " % 4i: %8p\n", 159 | i, d->data[i]); 160 | } 161 | } 162 | mutex_unlock(&dev->lock); 163 | return 0; 164 | } 165 | 166 | /* 167 | * Tie the sequence operators up. 168 | */ 169 | static struct seq_operations scull_seq_ops = { 170 | .start = scull_seq_start, 171 | .next = scull_seq_next, 172 | .stop = scull_seq_stop, 173 | .show = scull_seq_show 174 | }; 175 | 176 | /* 177 | * Now to implement the /proc files we need only make an open 178 | * method which sets up the sequence operators. 179 | */ 180 | static int scullmem_proc_open(struct inode *inode, struct file *file) 181 | { 182 | return single_open(file, scull_read_procmem, NULL); 183 | } 184 | 185 | static int scullseq_proc_open(struct inode *inode, struct file *file) 186 | { 187 | return seq_open(file, &scull_seq_ops); 188 | } 189 | 190 | /* 191 | * Create a set of file operations for our proc files. 192 | */ 193 | static struct file_operations scullmem_proc_ops = { 194 | .owner = THIS_MODULE, 195 | .open = scullmem_proc_open, 196 | .read = seq_read, 197 | .llseek = seq_lseek, 198 | .release = single_release 199 | }; 200 | 201 | static struct file_operations scullseq_proc_ops = { 202 | .owner = THIS_MODULE, 203 | .open = scullseq_proc_open, 204 | .read = seq_read, 205 | .llseek = seq_lseek, 206 | .release = seq_release 207 | }; 208 | 209 | 210 | /* 211 | * Actually create (and remove) the /proc file(s). 212 | */ 213 | 214 | static void scull_create_proc(void) 215 | { 216 | proc_create_data("scullmem", 0 /* default mode */, 217 | NULL /* parent dir */, &scullmem_proc_ops, 218 | NULL /* client data */); 219 | proc_create("scullseq", 0, NULL, &scullseq_proc_ops); 220 | } 221 | 222 | static void scull_remove_proc(void) 223 | { 224 | /* no problem if it was not registered */ 225 | remove_proc_entry("scullmem", NULL /* parent dir */); 226 | remove_proc_entry("scullseq", NULL); 227 | } 228 | 229 | 230 | #endif /* SCULL_DEBUG */ 231 | 232 | 233 | 234 | 235 | 236 | /* 237 | * Open and close 238 | */ 239 | 240 | int scull_open(struct inode *inode, struct file *filp) 241 | { 242 | struct scull_dev *dev; /* device information */ 243 | 244 | dev = container_of(inode->i_cdev, struct scull_dev, cdev); 245 | filp->private_data = dev; /* for other methods */ 246 | 247 | /* now trim to 0 the length of the device if open was write-only */ 248 | if ( (filp->f_flags & O_ACCMODE) == O_WRONLY) { 249 | if (mutex_lock_interruptible(&dev->lock)) 250 | return -ERESTARTSYS; 251 | scull_trim(dev); /* ignore errors */ 252 | mutex_unlock(&dev->lock); 253 | } 254 | return 0; /* success */ 255 | } 256 | 257 | int scull_release(struct inode *inode, struct file *filp) 258 | { 259 | return 0; 260 | } 261 | /* 262 | * Follow the list 263 | */ 264 | struct scull_qset *scull_follow(struct scull_dev *dev, int n) 265 | { 266 | struct scull_qset *qs = dev->data; 267 | 268 | /* Allocate first qset explicitly if need be */ 269 | if (! qs) { 270 | qs = dev->data = kmalloc(sizeof(struct scull_qset), GFP_KERNEL); 271 | if (qs == NULL) 272 | return NULL; /* Never mind */ 273 | memset(qs, 0, sizeof(struct scull_qset)); 274 | } 275 | 276 | /* Then follow the list */ 277 | while (n--) { 278 | if (!qs->next) { 279 | qs->next = kmalloc(sizeof(struct scull_qset), GFP_KERNEL); 280 | if (qs->next == NULL) 281 | return NULL; /* Never mind */ 282 | memset(qs->next, 0, sizeof(struct scull_qset)); 283 | } 284 | qs = qs->next; 285 | continue; 286 | } 287 | return qs; 288 | } 289 | 290 | /* 291 | * Data management: read and write 292 | */ 293 | 294 | ssize_t scull_read(struct file *filp, char __user *buf, size_t count, 295 | loff_t *f_pos) 296 | { 297 | struct scull_dev *dev = filp->private_data; 298 | struct scull_qset *dptr; /* the first listitem */ 299 | int quantum = dev->quantum, qset = dev->qset; 300 | int itemsize = quantum * qset; /* how many bytes in the listitem */ 301 | int item, s_pos, q_pos, rest; 302 | ssize_t retval = 0; 303 | 304 | if (mutex_lock_interruptible(&dev->lock)) 305 | return -ERESTARTSYS; 306 | if (*f_pos >= dev->size) 307 | goto out; 308 | if (*f_pos + count > dev->size) 309 | count = dev->size - *f_pos; 310 | 311 | /* find listitem, qset index, and offset in the quantum */ 312 | item = (long)*f_pos / itemsize; 313 | rest = (long)*f_pos % itemsize; 314 | s_pos = rest / quantum; q_pos = rest % quantum; 315 | 316 | /* follow the list up to the right position (defined elsewhere) */ 317 | dptr = scull_follow(dev, item); 318 | 319 | if (dptr == NULL || !dptr->data || ! dptr->data[s_pos]) 320 | goto out; /* don't fill holes */ 321 | 322 | /* read only up to the end of this quantum */ 323 | if (count > quantum - q_pos) 324 | count = quantum - q_pos; 325 | 326 | if (copy_to_user(buf, dptr->data[s_pos] + q_pos, count)) { 327 | retval = -EFAULT; 328 | goto out; 329 | } 330 | *f_pos += count; 331 | retval = count; 332 | 333 | out: 334 | mutex_unlock(&dev->lock); 335 | return retval; 336 | } 337 | 338 | ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, 339 | loff_t *f_pos) 340 | { 341 | struct scull_dev *dev = filp->private_data; 342 | struct scull_qset *dptr; 343 | int quantum = dev->quantum, qset = dev->qset; 344 | int itemsize = quantum * qset; 345 | int item, s_pos, q_pos, rest; 346 | ssize_t retval = -ENOMEM; /* value used in "goto out" statements */ 347 | 348 | if (mutex_lock_interruptible(&dev->lock)) 349 | return -ERESTARTSYS; 350 | 351 | /* find listitem, qset index and offset in the quantum */ 352 | item = (long)*f_pos / itemsize; 353 | rest = (long)*f_pos % itemsize; 354 | s_pos = rest / quantum; q_pos = rest % quantum; 355 | 356 | /* follow the list up to the right position */ 357 | dptr = scull_follow(dev, item); 358 | if (dptr == NULL) 359 | goto out; 360 | if (!dptr->data) { 361 | dptr->data = kmalloc(qset * sizeof(char *), GFP_KERNEL); 362 | if (!dptr->data) 363 | goto out; 364 | memset(dptr->data, 0, qset * sizeof(char *)); 365 | } 366 | if (!dptr->data[s_pos]) { 367 | dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL); 368 | if (!dptr->data[s_pos]) 369 | goto out; 370 | } 371 | /* write only up to the end of this quantum */ 372 | if (count > quantum - q_pos) 373 | count = quantum - q_pos; 374 | 375 | if (copy_from_user(dptr->data[s_pos]+q_pos, buf, count)) { 376 | retval = -EFAULT; 377 | goto out; 378 | } 379 | *f_pos += count; 380 | retval = count; 381 | 382 | /* update the size */ 383 | if (dev->size < *f_pos) 384 | dev->size = *f_pos; 385 | 386 | out: 387 | mutex_unlock(&dev->lock); 388 | return retval; 389 | } 390 | 391 | /* 392 | * The ioctl() implementation 393 | */ 394 | 395 | long scull_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 396 | { 397 | 398 | int err = 0, tmp; 399 | int retval = 0; 400 | 401 | /* 402 | * extract the type and number bitfields, and don't decode 403 | * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok() 404 | */ 405 | if (_IOC_TYPE(cmd) != SCULL_IOC_MAGIC) return -ENOTTY; 406 | if (_IOC_NR(cmd) > SCULL_IOC_MAXNR) return -ENOTTY; 407 | 408 | /* 409 | * the direction is a bitmask, and VERIFY_WRITE catches R/W 410 | * transfers. `Type' is user-oriented, while 411 | * access_ok is kernel-oriented, so the concept of "read" and 412 | * "write" is reversed 413 | */ 414 | if (_IOC_DIR(cmd) & _IOC_READ) 415 | err = !access_ok_wrapper(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); 416 | else if (_IOC_DIR(cmd) & _IOC_WRITE) 417 | err = !access_ok_wrapper(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); 418 | if (err) return -EFAULT; 419 | 420 | switch(cmd) { 421 | 422 | case SCULL_IOCRESET: 423 | scull_quantum = SCULL_QUANTUM; 424 | scull_qset = SCULL_QSET; 425 | break; 426 | 427 | case SCULL_IOCSQUANTUM: /* Set: arg points to the value */ 428 | if (! capable (CAP_SYS_ADMIN)) 429 | return -EPERM; 430 | retval = __get_user(scull_quantum, (int __user *)arg); 431 | break; 432 | 433 | case SCULL_IOCTQUANTUM: /* Tell: arg is the value */ 434 | if (! capable (CAP_SYS_ADMIN)) 435 | return -EPERM; 436 | scull_quantum = arg; 437 | break; 438 | 439 | case SCULL_IOCGQUANTUM: /* Get: arg is pointer to result */ 440 | retval = __put_user(scull_quantum, (int __user *)arg); 441 | break; 442 | 443 | case SCULL_IOCQQUANTUM: /* Query: return it (it's positive) */ 444 | return scull_quantum; 445 | 446 | case SCULL_IOCXQUANTUM: /* eXchange: use arg as pointer */ 447 | if (! capable (CAP_SYS_ADMIN)) 448 | return -EPERM; 449 | tmp = scull_quantum; 450 | retval = __get_user(scull_quantum, (int __user *)arg); 451 | if (retval == 0) 452 | retval = __put_user(tmp, (int __user *)arg); 453 | break; 454 | 455 | case SCULL_IOCHQUANTUM: /* sHift: like Tell + Query */ 456 | if (! capable (CAP_SYS_ADMIN)) 457 | return -EPERM; 458 | tmp = scull_quantum; 459 | scull_quantum = arg; 460 | return tmp; 461 | 462 | case SCULL_IOCSQSET: 463 | if (! capable (CAP_SYS_ADMIN)) 464 | return -EPERM; 465 | retval = __get_user(scull_qset, (int __user *)arg); 466 | break; 467 | 468 | case SCULL_IOCTQSET: 469 | if (! capable (CAP_SYS_ADMIN)) 470 | return -EPERM; 471 | scull_qset = arg; 472 | break; 473 | 474 | case SCULL_IOCGQSET: 475 | retval = __put_user(scull_qset, (int __user *)arg); 476 | break; 477 | 478 | case SCULL_IOCQQSET: 479 | return scull_qset; 480 | 481 | case SCULL_IOCXQSET: 482 | if (! capable (CAP_SYS_ADMIN)) 483 | return -EPERM; 484 | tmp = scull_qset; 485 | retval = __get_user(scull_qset, (int __user *)arg); 486 | if (retval == 0) 487 | retval = put_user(tmp, (int __user *)arg); 488 | break; 489 | 490 | case SCULL_IOCHQSET: 491 | if (! capable (CAP_SYS_ADMIN)) 492 | return -EPERM; 493 | tmp = scull_qset; 494 | scull_qset = arg; 495 | return tmp; 496 | 497 | /* 498 | * The following two change the buffer size for scullpipe. 499 | * The scullpipe device uses this same ioctl method, just to 500 | * write less code. Actually, it's the same driver, isn't it? 501 | */ 502 | 503 | case SCULL_P_IOCTSIZE: 504 | scull_p_buffer = arg; 505 | break; 506 | 507 | case SCULL_P_IOCQSIZE: 508 | return scull_p_buffer; 509 | 510 | 511 | default: /* redundant, as cmd was checked against MAXNR */ 512 | return -ENOTTY; 513 | } 514 | return retval; 515 | 516 | } 517 | 518 | 519 | 520 | /* 521 | * The "extended" operations -- only seek 522 | */ 523 | 524 | loff_t scull_llseek(struct file *filp, loff_t off, int whence) 525 | { 526 | struct scull_dev *dev = filp->private_data; 527 | loff_t newpos; 528 | 529 | switch(whence) { 530 | case 0: /* SEEK_SET */ 531 | newpos = off; 532 | break; 533 | 534 | case 1: /* SEEK_CUR */ 535 | newpos = filp->f_pos + off; 536 | break; 537 | 538 | case 2: /* SEEK_END */ 539 | newpos = dev->size + off; 540 | break; 541 | 542 | default: /* can't happen */ 543 | return -EINVAL; 544 | } 545 | if (newpos < 0) return -EINVAL; 546 | filp->f_pos = newpos; 547 | return newpos; 548 | } 549 | 550 | 551 | 552 | struct file_operations scull_fops = { 553 | .owner = THIS_MODULE, 554 | .llseek = scull_llseek, 555 | .read = scull_read, 556 | .write = scull_write, 557 | .unlocked_ioctl = scull_ioctl, 558 | .open = scull_open, 559 | .release = scull_release, 560 | }; 561 | 562 | /* 563 | * Finally, the module stuff 564 | */ 565 | 566 | /* 567 | * The cleanup function is used to handle initialization failures as well. 568 | * Thefore, it must be careful to work correctly even if some of the items 569 | * have not been initialized 570 | */ 571 | void scull_cleanup_module(void) 572 | { 573 | int i; 574 | dev_t devno = MKDEV(scull_major, scull_minor); 575 | 576 | /* Get rid of our char dev entries */ 577 | if (scull_devices) { 578 | for (i = 0; i < scull_nr_devs; i++) { 579 | scull_trim(scull_devices + i); 580 | cdev_del(&scull_devices[i].cdev); 581 | } 582 | kfree(scull_devices); 583 | } 584 | 585 | #ifdef SCULL_DEBUG /* use proc only if debugging */ 586 | scull_remove_proc(); 587 | #endif 588 | 589 | /* cleanup_module is never called if registering failed */ 590 | unregister_chrdev_region(devno, scull_nr_devs); 591 | 592 | /* and call the cleanup functions for friend devices */ 593 | scull_p_cleanup(); 594 | scull_access_cleanup(); 595 | 596 | } 597 | 598 | 599 | /* 600 | * Set up the char_dev structure for this device. 601 | */ 602 | static void scull_setup_cdev(struct scull_dev *dev, int index) 603 | { 604 | int err, devno = MKDEV(scull_major, scull_minor + index); 605 | 606 | cdev_init(&dev->cdev, &scull_fops); 607 | dev->cdev.owner = THIS_MODULE; 608 | dev->cdev.ops = &scull_fops; 609 | err = cdev_add (&dev->cdev, devno, 1); 610 | /* Fail gracefully if need be */ 611 | if (err) 612 | printk(KERN_NOTICE "Error %d adding scull%d", err, index); 613 | } 614 | 615 | 616 | int scull_init_module(void) 617 | { 618 | int result, i; 619 | dev_t dev = 0; 620 | 621 | /* 622 | * Get a range of minor numbers to work with, asking for a dynamic 623 | * major unless directed otherwise at load time. 624 | */ 625 | if (scull_major) { 626 | dev = MKDEV(scull_major, scull_minor); 627 | result = register_chrdev_region(dev, scull_nr_devs, "scull"); 628 | } else { 629 | result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs, 630 | "scull"); 631 | scull_major = MAJOR(dev); 632 | } 633 | if (result < 0) { 634 | printk(KERN_WARNING "scull: can't get major %d\n", scull_major); 635 | return result; 636 | } 637 | 638 | /* 639 | * allocate the devices -- we can't have them static, as the number 640 | * can be specified at load time 641 | */ 642 | scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL); 643 | if (!scull_devices) { 644 | result = -ENOMEM; 645 | goto fail; /* Make this more graceful */ 646 | } 647 | memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev)); 648 | 649 | /* Initialize each device. */ 650 | for (i = 0; i < scull_nr_devs; i++) { 651 | scull_devices[i].quantum = scull_quantum; 652 | scull_devices[i].qset = scull_qset; 653 | mutex_init(&scull_devices[i].lock); 654 | scull_setup_cdev(&scull_devices[i], i); 655 | } 656 | 657 | /* At this point call the init function for any friend device */ 658 | dev = MKDEV(scull_major, scull_minor + scull_nr_devs); 659 | dev += scull_p_init(dev); 660 | dev += scull_access_init(dev); 661 | 662 | #ifdef SCULL_DEBUG /* only when debugging */ 663 | scull_create_proc(); 664 | #endif 665 | 666 | return 0; /* succeed */ 667 | 668 | fail: 669 | scull_cleanup_module(); 670 | return result; 671 | } 672 | 673 | module_init(scull_init_module); 674 | module_exit(scull_cleanup_module); 675 | -------------------------------------------------------------------------------- /Code_Examples/scull/modules.order: -------------------------------------------------------------------------------- 1 | /home/dom/LDD3-Notes/Code_Examples/temp/scull.ko 2 | -------------------------------------------------------------------------------- /Code_Examples/scull/pipe.c: -------------------------------------------------------------------------------- 1 | /* 2 | * pipe.c -- fifo driver for scull 3 | * 4 | * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet 5 | * Copyright (C) 2001 O'Reilly & Associates 6 | * 7 | * The source code in this file can be freely used, adapted, 8 | * and redistributed in source or binary form, so long as an 9 | * acknowledgment appears in derived source files. The citation 10 | * should list that the code comes from the book "Linux Device 11 | * Drivers" by Alessandro Rubini and Jonathan Corbet, published 12 | * by O'Reilly & Associates. No warranty is attached; 13 | * we cannot take responsibility for errors or fitness for use. 14 | * 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include /* printk(), min() */ 21 | #include /* kmalloc() */ 22 | #include /* everything... */ 23 | #include 24 | #include /* error codes */ 25 | #include /* size_t */ 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "scull.h" /* local definitions */ 35 | 36 | struct scull_pipe { 37 | wait_queue_head_t inq, outq; /* read and write queues */ 38 | char *buffer, *end; /* begin of buf, end of buf */ 39 | int buffersize; /* used in pointer arithmetic */ 40 | char *rp, *wp; /* where to read, where to write */ 41 | int nreaders, nwriters; /* number of openings for r/w */ 42 | struct fasync_struct *async_queue; /* asynchronous readers */ 43 | struct mutex lock; /* mutual exclusion mutex */ 44 | struct cdev cdev; /* Char device structure */ 45 | }; 46 | 47 | /* parameters */ 48 | static int scull_p_nr_devs = SCULL_P_NR_DEVS; /* number of pipe devices */ 49 | int scull_p_buffer = SCULL_P_BUFFER; /* buffer size */ 50 | dev_t scull_p_devno; /* Our first device number */ 51 | 52 | module_param(scull_p_nr_devs, int, 0); /* FIXME check perms */ 53 | module_param(scull_p_buffer, int, 0); 54 | 55 | static struct scull_pipe *scull_p_devices; 56 | 57 | static int scull_p_fasync(int fd, struct file *filp, int mode); 58 | static int spacefree(struct scull_pipe *dev); 59 | /* 60 | * Open and close 61 | */ 62 | 63 | 64 | static int scull_p_open(struct inode *inode, struct file *filp) 65 | { 66 | struct scull_pipe *dev; 67 | 68 | dev = container_of(inode->i_cdev, struct scull_pipe, cdev); 69 | filp->private_data = dev; 70 | 71 | if (mutex_lock_interruptible(&dev->lock)) 72 | return -ERESTARTSYS; 73 | if (!dev->buffer) { 74 | /* allocate the buffer */ 75 | dev->buffer = kmalloc(scull_p_buffer, GFP_KERNEL); 76 | if (!dev->buffer) { 77 | mutex_unlock(&dev->lock); 78 | return -ENOMEM; 79 | } 80 | } 81 | dev->buffersize = scull_p_buffer; 82 | dev->end = dev->buffer + dev->buffersize; 83 | dev->rp = dev->wp = dev->buffer; /* rd and wr from the beginning */ 84 | 85 | /* use f_mode,not f_flags: it's cleaner (fs/open.c tells why) */ 86 | if (filp->f_mode & FMODE_READ) 87 | dev->nreaders++; 88 | if (filp->f_mode & FMODE_WRITE) 89 | dev->nwriters++; 90 | mutex_unlock(&dev->lock); 91 | 92 | return nonseekable_open(inode, filp); 93 | } 94 | 95 | 96 | 97 | static int scull_p_release(struct inode *inode, struct file *filp) 98 | { 99 | struct scull_pipe *dev = filp->private_data; 100 | 101 | /* remove this filp from the asynchronously notified filp's */ 102 | scull_p_fasync(-1, filp, 0); 103 | mutex_lock(&dev->lock); 104 | if (filp->f_mode & FMODE_READ) 105 | dev->nreaders--; 106 | if (filp->f_mode & FMODE_WRITE) 107 | dev->nwriters--; 108 | if (dev->nreaders + dev->nwriters == 0) { 109 | kfree(dev->buffer); 110 | dev->buffer = NULL; /* the other fields are not checked on open */ 111 | } 112 | mutex_unlock(&dev->lock); 113 | return 0; 114 | } 115 | 116 | 117 | /* 118 | * Data management: read and write 119 | */ 120 | 121 | static ssize_t scull_p_read (struct file *filp, char __user *buf, size_t count, 122 | loff_t *f_pos) 123 | { 124 | struct scull_pipe *dev = filp->private_data; 125 | 126 | if (mutex_lock_interruptible(&dev->lock)) 127 | return -ERESTARTSYS; 128 | 129 | while (dev->rp == dev->wp) { /* nothing to read */ 130 | mutex_unlock(&dev->lock); /* release the lock */ 131 | if (filp->f_flags & O_NONBLOCK) 132 | return -EAGAIN; 133 | PDEBUG("\"%s\" reading: going to sleep\n", current->comm); 134 | if (wait_event_interruptible(dev->inq, (dev->rp != dev->wp))) 135 | return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ 136 | /* otherwise loop, but first reacquire the lock */ 137 | if (mutex_lock_interruptible(&dev->lock)) 138 | return -ERESTARTSYS; 139 | } 140 | /* ok, data is there, return something */ 141 | if (dev->wp > dev->rp) 142 | count = min(count, (size_t)(dev->wp - dev->rp)); 143 | else /* the write pointer has wrapped, return data up to dev->end */ 144 | count = min(count, (size_t)(dev->end - dev->rp)); 145 | if (copy_to_user(buf, dev->rp, count)) { 146 | mutex_unlock (&dev->lock); 147 | return -EFAULT; 148 | } 149 | dev->rp += count; 150 | if (dev->rp == dev->end) 151 | dev->rp = dev->buffer; /* wrapped */ 152 | mutex_unlock (&dev->lock); 153 | 154 | /* finally, awake any writers and return */ 155 | wake_up_interruptible(&dev->outq); 156 | PDEBUG("\"%s\" did read %li bytes\n",current->comm, (long)count); 157 | return count; 158 | } 159 | 160 | /* Wait for space for writing; caller must hold device semaphore. On 161 | * error the semaphore will be released before returning. */ 162 | static int scull_getwritespace(struct scull_pipe *dev, struct file *filp) 163 | { 164 | while (spacefree(dev) == 0) { /* full */ 165 | DEFINE_WAIT(wait); 166 | 167 | mutex_unlock(&dev->lock); 168 | if (filp->f_flags & O_NONBLOCK) 169 | return -EAGAIN; 170 | PDEBUG("\"%s\" writing: going to sleep\n",current->comm); 171 | prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE); 172 | if (spacefree(dev) == 0) 173 | schedule(); 174 | finish_wait(&dev->outq, &wait); 175 | if (signal_pending(current)) 176 | return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ 177 | if (mutex_lock_interruptible(&dev->lock)) 178 | return -ERESTARTSYS; 179 | } 180 | return 0; 181 | } 182 | 183 | /* How much space is free? */ 184 | static int spacefree(struct scull_pipe *dev) 185 | { 186 | if (dev->rp == dev->wp) 187 | return dev->buffersize - 1; 188 | return ((dev->rp + dev->buffersize - dev->wp) % dev->buffersize) - 1; 189 | } 190 | 191 | static ssize_t scull_p_write(struct file *filp, const char __user *buf, size_t count, 192 | loff_t *f_pos) 193 | { 194 | struct scull_pipe *dev = filp->private_data; 195 | int result; 196 | 197 | if (mutex_lock_interruptible(&dev->lock)) 198 | return -ERESTARTSYS; 199 | 200 | /* Make sure there's space to write */ 201 | result = scull_getwritespace(dev, filp); 202 | if (result) 203 | return result; /* scull_getwritespace called up(&dev->sem) */ 204 | 205 | /* ok, space is there, accept something */ 206 | count = min(count, (size_t)spacefree(dev)); 207 | if (dev->wp >= dev->rp) 208 | count = min(count, (size_t)(dev->end - dev->wp)); /* to end-of-buf */ 209 | else /* the write pointer has wrapped, fill up to rp-1 */ 210 | count = min(count, (size_t)(dev->rp - dev->wp - 1)); 211 | PDEBUG("Going to accept %li bytes to %p from %p\n", (long)count, dev->wp, buf); 212 | if (copy_from_user(dev->wp, buf, count)) { 213 | mutex_unlock(&dev->lock); 214 | return -EFAULT; 215 | } 216 | dev->wp += count; 217 | if (dev->wp == dev->end) 218 | dev->wp = dev->buffer; /* wrapped */ 219 | mutex_unlock(&dev->lock); 220 | 221 | /* finally, awake any reader */ 222 | wake_up_interruptible(&dev->inq); /* blocked in read() and select() */ 223 | 224 | /* and signal asynchronous readers, explained late in chapter 5 */ 225 | if (dev->async_queue) 226 | kill_fasync(&dev->async_queue, SIGIO, POLL_IN); 227 | PDEBUG("\"%s\" did write %li bytes\n",current->comm, (long)count); 228 | return count; 229 | } 230 | 231 | static unsigned int scull_p_poll(struct file *filp, poll_table *wait) 232 | { 233 | struct scull_pipe *dev = filp->private_data; 234 | unsigned int mask = 0; 235 | 236 | /* 237 | * The buffer is circular; it is considered full 238 | * if "wp" is right behind "rp" and empty if the 239 | * two are equal. 240 | */ 241 | mutex_lock(&dev->lock); 242 | poll_wait(filp, &dev->inq, wait); 243 | poll_wait(filp, &dev->outq, wait); 244 | if (dev->rp != dev->wp) 245 | mask |= POLLIN | POLLRDNORM; /* readable */ 246 | if (spacefree(dev)) 247 | mask |= POLLOUT | POLLWRNORM; /* writable */ 248 | mutex_unlock(&dev->lock); 249 | return mask; 250 | } 251 | 252 | 253 | 254 | 255 | 256 | static int scull_p_fasync(int fd, struct file *filp, int mode) 257 | { 258 | struct scull_pipe *dev = filp->private_data; 259 | 260 | return fasync_helper(fd, filp, mode, &dev->async_queue); 261 | } 262 | 263 | 264 | 265 | /* FIXME this should use seq_file */ 266 | #ifdef SCULL_DEBUG 267 | 268 | static int scull_read_p_mem(struct seq_file *s, void *v) 269 | { 270 | int i; 271 | struct scull_pipe *p; 272 | 273 | #define LIMIT (PAGE_SIZE-200) /* don't print any more after this size */ 274 | seq_printf(s, "Default buffersize is %i\n", scull_p_buffer); 275 | for(i = 0; icount <= LIMIT; i++) { 276 | p = &scull_p_devices[i]; 277 | if (mutex_lock_interruptible(&p->lock)) 278 | return -ERESTARTSYS; 279 | seq_printf(s, "\nDevice %i: %p\n", i, p); 280 | /* seq_printf(s, " Queues: %p %p\n", p->inq, p->outq);*/ 281 | seq_printf(s, " Buffer: %p to %p (%i bytes)\n", p->buffer, p->end, p->buffersize); 282 | seq_printf(s, " rp %p wp %p\n", p->rp, p->wp); 283 | seq_printf(s, " readers %i writers %i\n", p->nreaders, p->nwriters); 284 | mutex_unlock(&p->lock); 285 | } 286 | return 0; 287 | } 288 | 289 | static int scullpipe_proc_open(struct inode *inode, struct file *file) 290 | { 291 | return single_open(file, scull_read_p_mem, NULL); 292 | } 293 | 294 | static struct file_operations scullpipe_proc_ops = { 295 | .owner = THIS_MODULE, 296 | .open = scullpipe_proc_open, 297 | .read = seq_read, 298 | .llseek = seq_lseek, 299 | .release = single_release 300 | }; 301 | 302 | #endif 303 | 304 | 305 | 306 | /* 307 | * The file operations for the pipe device 308 | * (some are overlayed with bare scull) 309 | */ 310 | struct file_operations scull_pipe_fops = { 311 | .owner = THIS_MODULE, 312 | .llseek = no_llseek, 313 | .read = scull_p_read, 314 | .write = scull_p_write, 315 | .poll = scull_p_poll, 316 | .unlocked_ioctl = scull_ioctl, 317 | .open = scull_p_open, 318 | .release = scull_p_release, 319 | .fasync = scull_p_fasync, 320 | }; 321 | 322 | 323 | /* 324 | * Set up a cdev entry. 325 | */ 326 | static void scull_p_setup_cdev(struct scull_pipe *dev, int index) 327 | { 328 | int err, devno = scull_p_devno + index; 329 | 330 | cdev_init(&dev->cdev, &scull_pipe_fops); 331 | dev->cdev.owner = THIS_MODULE; 332 | err = cdev_add (&dev->cdev, devno, 1); 333 | /* Fail gracefully if need be */ 334 | if (err) 335 | printk(KERN_NOTICE "Error %d adding scullpipe%d", err, index); 336 | } 337 | 338 | 339 | 340 | /* 341 | * Initialize the pipe devs; return how many we did. 342 | */ 343 | int scull_p_init(dev_t firstdev) 344 | { 345 | int i, result; 346 | 347 | result = register_chrdev_region(firstdev, scull_p_nr_devs, "scullp"); 348 | if (result < 0) { 349 | printk(KERN_NOTICE "Unable to get scullp region, error %d\n", result); 350 | return 0; 351 | } 352 | scull_p_devno = firstdev; 353 | scull_p_devices = kmalloc(scull_p_nr_devs * sizeof(struct scull_pipe), GFP_KERNEL); 354 | if (scull_p_devices == NULL) { 355 | unregister_chrdev_region(firstdev, scull_p_nr_devs); 356 | return 0; 357 | } 358 | memset(scull_p_devices, 0, scull_p_nr_devs * sizeof(struct scull_pipe)); 359 | for (i = 0; i < scull_p_nr_devs; i++) { 360 | init_waitqueue_head(&(scull_p_devices[i].inq)); 361 | init_waitqueue_head(&(scull_p_devices[i].outq)); 362 | mutex_init(&scull_p_devices[i].lock); 363 | scull_p_setup_cdev(scull_p_devices + i, i); 364 | } 365 | #ifdef SCULL_DEBUG 366 | proc_create("scullpipe", 0, NULL, &scullpipe_proc_ops); 367 | #endif 368 | return scull_p_nr_devs; 369 | } 370 | 371 | /* 372 | * This is called by cleanup_module or on failure. 373 | * It is required to never fail, even if nothing was initialized first 374 | */ 375 | void scull_p_cleanup(void) 376 | { 377 | int i; 378 | 379 | #ifdef SCULL_DEBUG 380 | remove_proc_entry("scullpipe", NULL); 381 | #endif 382 | 383 | if (!scull_p_devices) 384 | return; /* nothing else to release */ 385 | 386 | for (i = 0; i < scull_p_nr_devs; i++) { 387 | cdev_del(&scull_p_devices[i].cdev); 388 | kfree(scull_p_devices[i].buffer); 389 | } 390 | kfree(scull_p_devices); 391 | unregister_chrdev_region(scull_p_devno, scull_p_nr_devs); 392 | scull_p_devices = NULL; /* pedantic */ 393 | } 394 | -------------------------------------------------------------------------------- /Code_Examples/scull/scull.h: -------------------------------------------------------------------------------- 1 | /* 2 | * scull.h -- definitions for the char module 3 | * 4 | * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet 5 | * Copyright (C) 2001 O'Reilly & Associates 6 | * 7 | * The source code in this file can be freely used, adapted, 8 | * and redistributed in source or binary form, so long as an 9 | * acknowledgment appears in derived source files. The citation 10 | * should list that the code comes from the book "Linux Device 11 | * Drivers" by Alessandro Rubini and Jonathan Corbet, published 12 | * by O'Reilly & Associates. No warranty is attached; 13 | * we cannot take responsibility for errors or fitness for use. 14 | * 15 | * $Id: scull.h,v 1.15 2004/11/04 17:51:18 rubini Exp $ 16 | */ 17 | 18 | #ifndef _SCULL_H_ 19 | #define _SCULL_H_ 20 | 21 | #include /* needed for the _IOW etc stuff used later */ 22 | 23 | /* 24 | * Macros to help debugging 25 | */ 26 | 27 | #undef PDEBUG /* undef it, just in case */ 28 | #ifdef SCULL_DEBUG 29 | # ifdef __KERNEL__ 30 | /* This one if debugging is on, and kernel space */ 31 | # define PDEBUG(fmt, args...) printk( KERN_DEBUG "scull: " fmt, ## args) 32 | # else 33 | /* This one for user space */ 34 | # define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args) 35 | # endif 36 | #else 37 | # define PDEBUG(fmt, args...) /* not debugging: nothing */ 38 | #endif 39 | 40 | #undef PDEBUGG 41 | #define PDEBUGG(fmt, args...) /* nothing: it's a placeholder */ 42 | 43 | #ifndef SCULL_MAJOR 44 | #define SCULL_MAJOR 0 /* dynamic major by default */ 45 | #endif 46 | 47 | #ifndef SCULL_NR_DEVS 48 | #define SCULL_NR_DEVS 4 /* scull0 through scull3 */ 49 | #endif 50 | 51 | #ifndef SCULL_P_NR_DEVS 52 | #define SCULL_P_NR_DEVS 4 /* scullpipe0 through scullpipe3 */ 53 | #endif 54 | 55 | /* 56 | * The bare device is a variable-length region of memory. 57 | * Use a linked list of indirect blocks. 58 | * 59 | * "scull_dev->data" points to an array of pointers, each 60 | * pointer refers to a memory area of SCULL_QUANTUM bytes. 61 | * 62 | * The array (quantum-set) is SCULL_QSET long. 63 | */ 64 | #ifndef SCULL_QUANTUM 65 | #define SCULL_QUANTUM 4000 66 | #endif 67 | 68 | #ifndef SCULL_QSET 69 | #define SCULL_QSET 1000 70 | #endif 71 | 72 | /* 73 | * The pipe device is a simple circular buffer. Here its default size 74 | */ 75 | #ifndef SCULL_P_BUFFER 76 | #define SCULL_P_BUFFER 4000 77 | #endif 78 | 79 | /* 80 | * Representation of scull quantum sets. 81 | */ 82 | struct scull_qset { 83 | void **data; 84 | struct scull_qset *next; 85 | }; 86 | 87 | struct scull_dev { 88 | struct scull_qset *data; /* Pointer to first quantum set */ 89 | int quantum; /* the current quantum size */ 90 | int qset; /* the current array size */ 91 | unsigned long size; /* amount of data stored here */ 92 | unsigned int access_key; /* used by sculluid and scullpriv */ 93 | struct mutex lock; /* mutual exclusion semaphore */ 94 | struct cdev cdev; /* Char device structure */ 95 | }; 96 | 97 | /* 98 | * Split minors in two parts 99 | */ 100 | #define TYPE(minor) (((minor) >> 4) & 0xf) /* high nibble */ 101 | #define NUM(minor) ((minor) & 0xf) /* low nibble */ 102 | 103 | 104 | /* 105 | * The different configurable parameters 106 | */ 107 | extern int scull_major; /* main.c */ 108 | extern int scull_nr_devs; 109 | extern int scull_quantum; 110 | extern int scull_qset; 111 | 112 | extern int scull_p_buffer; /* pipe.c */ 113 | 114 | 115 | /* 116 | * Prototypes for shared functions 117 | */ 118 | 119 | int scull_p_init(dev_t dev); 120 | void scull_p_cleanup(void); 121 | int scull_access_init(dev_t dev); 122 | void scull_access_cleanup(void); 123 | 124 | int scull_trim(struct scull_dev *dev); 125 | 126 | ssize_t scull_read(struct file *filp, char __user *buf, size_t count, 127 | loff_t *f_pos); 128 | ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, 129 | loff_t *f_pos); 130 | loff_t scull_llseek(struct file *filp, loff_t off, int whence); 131 | long scull_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); 132 | 133 | 134 | /* 135 | * Ioctl definitions 136 | */ 137 | 138 | /* Use 'k' as magic number */ 139 | #define SCULL_IOC_MAGIC 'k' 140 | /* Please use a different 8-bit number in your code */ 141 | 142 | #define SCULL_IOCRESET _IO(SCULL_IOC_MAGIC, 0) 143 | 144 | /* 145 | * S means "Set" through a ptr, 146 | * T means "Tell" directly with the argument value 147 | * G means "Get": reply by setting through a pointer 148 | * Q means "Query": response is on the return value 149 | * X means "eXchange": switch G and S atomically 150 | * H means "sHift": switch T and Q atomically 151 | */ 152 | #define SCULL_IOCSQUANTUM _IOW(SCULL_IOC_MAGIC, 1, int) 153 | #define SCULL_IOCSQSET _IOW(SCULL_IOC_MAGIC, 2, int) 154 | #define SCULL_IOCTQUANTUM _IO(SCULL_IOC_MAGIC, 3) 155 | #define SCULL_IOCTQSET _IO(SCULL_IOC_MAGIC, 4) 156 | #define SCULL_IOCGQUANTUM _IOR(SCULL_IOC_MAGIC, 5, int) 157 | #define SCULL_IOCGQSET _IOR(SCULL_IOC_MAGIC, 6, int) 158 | #define SCULL_IOCQQUANTUM _IO(SCULL_IOC_MAGIC, 7) 159 | #define SCULL_IOCQQSET _IO(SCULL_IOC_MAGIC, 8) 160 | #define SCULL_IOCXQUANTUM _IOWR(SCULL_IOC_MAGIC, 9, int) 161 | #define SCULL_IOCXQSET _IOWR(SCULL_IOC_MAGIC,10, int) 162 | #define SCULL_IOCHQUANTUM _IO(SCULL_IOC_MAGIC, 11) 163 | #define SCULL_IOCHQSET _IO(SCULL_IOC_MAGIC, 12) 164 | 165 | /* 166 | * The other entities only have "Tell" and "Query", because they're 167 | * not printed in the book, and there's no need to have all six. 168 | * (The previous stuff was only there to show different ways to do it. 169 | */ 170 | #define SCULL_P_IOCTSIZE _IO(SCULL_IOC_MAGIC, 13) 171 | #define SCULL_P_IOCQSIZE _IO(SCULL_IOC_MAGIC, 14) 172 | /* ... more to come */ 173 | 174 | #define SCULL_IOC_MAXNR 14 175 | 176 | #endif /* _SCULL_H_ */ 177 | -------------------------------------------------------------------------------- /Code_Examples/scull/scull.init: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Sample init script for the scull driver module 3 | 4 | DEVICE="scull" 5 | SECTION="misc" 6 | 7 | # The list of filenames and minor numbers: $PREFIX is prefixed to all names 8 | PREFIX="scull" 9 | FILES=" 0 0 1 1 2 2 3 3 priv 16 10 | pipe0 32 pipe1 33 pipe2 34 pipe3 35 11 | single 48 uid 64 wuid 80" 12 | 13 | INSMOD=/sbin/insmod; # use /sbin/modprobe if you prefer 14 | 15 | function device_specific_post_load () { 16 | true; # fill at will 17 | } 18 | function device_specific_pre_unload () { 19 | true; # fill at will 20 | } 21 | 22 | # Everything below this line should work unchanged for any char device. 23 | # Obviously, however, no options on the command line: either in 24 | # /etc/${DEVICE}.conf or /etc/modules.conf (if modprobe is used) 25 | 26 | # Optional configuration file: format is 27 | # owner 28 | # group 29 | # mode 30 | # options 31 | CFG=/etc/${DEVICE}.conf 32 | 33 | # kernel version, used to look for modules 34 | KERNEL=`uname -r` 35 | 36 | #FIXME: it looks like there is no misc section. Where should it be? 37 | MODDIR="/lib/modules/${KERNEL}/kernel/drivers/${SECTION}" 38 | if [ ! -d $MODDIR ]; then MODDIR="/lib/modules/${KERNEL}/${SECTION}"; fi 39 | 40 | # Root or die 41 | if [ "$(id -u)" != "0" ] 42 | then 43 | echo "You must be root to load or unload kernel modules" 44 | exit 1 45 | fi 46 | 47 | # Read configuration file 48 | if [ -r $CFG ]; then 49 | OWNER=`awk "\\$1==\"owner\" {print \\$2}" $CFG` 50 | GROUP=`awk "\\$1==\"group\" {print \\$2}" $CFG` 51 | MODE=`awk "\\$1==\"mode\" {print \\$2}" $CFG` 52 | # The options string may include extra blanks or only blanks 53 | OPTIONS=`sed -n '/^options / s/options //p' $CFG` 54 | fi 55 | 56 | 57 | # Create device files 58 | function create_files () { 59 | cd /dev 60 | local devlist="" 61 | local file 62 | while true; do 63 | if [ $# -lt 2 ]; then break; fi 64 | file="${DEVICE}$1" 65 | mknod $file c $MAJOR $2 66 | devlist="$devlist $file" 67 | shift 2 68 | done 69 | if [ -n "$OWNER" ]; then chown $OWNER $devlist; fi 70 | if [ -n "$GROUP" ]; then chgrp $GROUP $devlist; fi 71 | if [ -n "$MODE" ]; then chmod $MODE $devlist; fi 72 | } 73 | 74 | # Remove device files 75 | function remove_files () { 76 | cd /dev 77 | local devlist="" 78 | local file 79 | while true; do 80 | if [ $# -lt 2 ]; then break; fi 81 | file="${DEVICE}$1" 82 | devlist="$devlist $file" 83 | shift 2 84 | done 85 | rm -f $devlist 86 | } 87 | 88 | # Load and create files 89 | function load_device () { 90 | 91 | if [ -f $MODDIR/$DEVICE.ko ]; then 92 | devpath=$MODDIR/$DEVICE.ko 93 | else if [ -f ./$DEVICE.ko ]; then 94 | devpath=./$DEVICE.ko 95 | else 96 | devpath=$DEVICE; # let insmod/modprobe guess 97 | fi; fi 98 | if [ "$devpath" != "$DEVICE" ]; then 99 | echo -n " (loading file $devpath)" 100 | fi 101 | 102 | if $INSMOD $devpath $OPTIONS; then 103 | MAJOR=`awk "\\$2==\"$DEVICE\" {print \\$1}" /proc/devices` 104 | remove_files $FILES 105 | create_files $FILES 106 | device_specific_post_load 107 | else 108 | echo " FAILED!" 109 | fi 110 | } 111 | 112 | # Unload and remove files 113 | function unload_device () { 114 | device_specific_pre_unload 115 | /sbin/rmmod $DEVICE 116 | remove_files $FILES 117 | } 118 | 119 | 120 | case "$1" in 121 | start) 122 | echo -n "Loading $DEVICE" 123 | load_device 124 | echo "." 125 | ;; 126 | stop) 127 | echo -n "Unloading $DEVICE" 128 | unload_device 129 | echo "." 130 | ;; 131 | force-reload|restart) 132 | echo -n "Reloading $DEVICE" 133 | unload_device 134 | load_device 135 | echo "." 136 | ;; 137 | *) 138 | echo "Usage: $0 {start|stop|restart|force-reload}" 139 | exit 1 140 | esac 141 | 142 | exit 0 143 | -------------------------------------------------------------------------------- /Code_Examples/scull/scull_load: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # $Id: scull_load,v 1.4 2004/11/03 06:19:49 rubini Exp $ 3 | module="scull" 4 | device="scull" 5 | mode="664" 6 | 7 | # Group: since distributions do it differently, look for wheel or use staff 8 | if grep -q '^staff:' /etc/group; then 9 | group="staff" 10 | else 11 | group="wheel" 12 | fi 13 | 14 | # invoke insmod with all arguments we got 15 | # and use a pathname, as insmod doesn't look in . by default 16 | insmod ./$module.ko $* || exit 1 17 | 18 | # retrieve major number 19 | major=$(awk "\$2==\"$module\" {print \$1}" /proc/devices) 20 | 21 | # Remove stale nodes and replace them, then give gid and perms 22 | # Usually the script is shorter, it's scull that has several devices in it. 23 | 24 | rm -f /dev/${device}[0-3] 25 | mknod /dev/${device}0 c $major 0 26 | mknod /dev/${device}1 c $major 1 27 | mknod /dev/${device}2 c $major 2 28 | mknod /dev/${device}3 c $major 3 29 | ln -sf ${device}0 /dev/${device} 30 | chgrp $group /dev/${device}[0-3] 31 | chmod $mode /dev/${device}[0-3] 32 | 33 | rm -f /dev/${device}pipe[0-3] 34 | mknod /dev/${device}pipe0 c $major 4 35 | mknod /dev/${device}pipe1 c $major 5 36 | mknod /dev/${device}pipe2 c $major 6 37 | mknod /dev/${device}pipe3 c $major 7 38 | ln -sf ${device}pipe0 /dev/${device}pipe 39 | chgrp $group /dev/${device}pipe[0-3] 40 | chmod $mode /dev/${device}pipe[0-3] 41 | 42 | rm -f /dev/${device}single 43 | mknod /dev/${device}single c $major 8 44 | chgrp $group /dev/${device}single 45 | chmod $mode /dev/${device}single 46 | 47 | rm -f /dev/${device}uid 48 | mknod /dev/${device}uid c $major 9 49 | chgrp $group /dev/${device}uid 50 | chmod $mode /dev/${device}uid 51 | 52 | rm -f /dev/${device}wuid 53 | mknod /dev/${device}wuid c $major 10 54 | chgrp $group /dev/${device}wuid 55 | chmod $mode /dev/${device}wuid 56 | 57 | rm -f /dev/${device}priv 58 | mknod /dev/${device}priv c $major 11 59 | chgrp $group /dev/${device}priv 60 | chmod $mode /dev/${device}priv 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Code_Examples/scull/scull_unload: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | module="scull" 3 | device="scull" 4 | 5 | # invoke rmmod with all arguments we got 6 | rmmod $module $* || exit 1 7 | 8 | # Remove stale nodes 9 | 10 | rm -f /dev/${device} /dev/${device}[0-3] 11 | rm -f /dev/${device}priv 12 | rm -f /dev/${device}pipe /dev/${device}pipe[0-3] 13 | rm -f /dev/${device}single 14 | rm -f /dev/${device}uid 15 | rm -f /dev/${device}wuid 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Code_Examples/socketCAN/README.md: -------------------------------------------------------------------------------- 1 | # Playing with SocketCAN 2 | 3 | Alright folks, some bonus content for you. 4 | 5 | While this section is not specifically a kernel module, it is a user-space program set that heavily uses the Linux SocketCAN API (which is a lot of kernel code relating to networking). This is like 1 step above kernel programming so I wanted to include it here. 6 | 7 | First, you will need the two source files: ReceiveRawPacket.c and SendRawPacket.c. The first file receives CAN data continuously, and the second file sends a one-time CAN message. 8 | 9 | Start by compiling both programs with: 10 | 11 | ```shell 12 | $ gcc -o CanReceive ReceiveRawPacket.c 13 | $ gcc -o CanSend SendRawPacket.c 14 | ``` 15 | 16 | Now, you will need to setup a virtual CAN bus, called vcan0: 17 | 18 | ```shell 19 | $ modprobe can 20 | $ modprobe can_raw 21 | $ modprobe vcan 22 | $ sudo ip link add dev vcan0 type vcan 23 | $ sudo ip link set up vcan0 24 | $ ip link show vcan0 25 | ``` 26 | 27 | Start by executing CanReceive and then CanSend. You should see this from the CanSend terminal: 28 | 29 | ```shell 30 | $ ./CanSend vcan0 31 | 32 | vcan0 at index 4 33 | Wrote 16 bytes 34 | ``` 35 | 36 | And see this from the CanReceive terminal output: 37 | 38 | ```shell 39 | $ ./CanReceive vcan0 40 | vcan0 at index 4 41 | Read 16 bytes 42 | CAN ID: 123 43 | CAN DLC: 8 44 | CAN DATA: 45 | de ad be ef 12 34 56 78 46 | ``` 47 | 48 | The CanReceive file will keep listening for more data, while the CanSend will only send once. You can run the CanSend file multiple times to see data sent multiple times. You can also monitor the CAN bus with a built-in tool called candump: 49 | 50 | ```shell 51 | $ candump vcan0 52 | 53 | vcan0 123 [8] DE AD BE EF 12 34 56 78 54 | ``` 55 | -------------------------------------------------------------------------------- /Code_Examples/socketCAN/ReceiveRawPacket.c: -------------------------------------------------------------------------------- 1 | // Code to test sending manual messages over a virtual can interface 2 | 3 | // Use these headers to communicate with a raw can data frame 4 | #include 5 | #include 6 | 7 | // Additional socket stuff needed by the socketCAN library 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | // And finally, the regular c types for having some fun! 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | int fd; //file descriptor for reading and writing 22 | int bytes_read; //number of bytes received over CAN 23 | int i; //used in a loop later on for printing 24 | 25 | // structure for CAN sockets includes: 26 | // address family, interface index, specific address info 27 | struct sockaddr_can addr; 28 | 29 | // structure for an individual frame in CAN 30 | struct can_frame frame; 31 | 32 | // Linux supports some standard ioctls to configure network devices. 33 | // They can be used on any socket's file descriptor regardless of the 34 | // family or type. Most of them pass an ifreq structure: 35 | struct ifreq ifr; 36 | 37 | // Check to make sure we have entered a CAN interface to use 38 | if (argc < 2) 39 | { 40 | printf("Please enter CAN bus to write to (ex: vcan0)\n"); 41 | printf("Args: Canbus\n"); 42 | return -1; 43 | } 44 | 45 | // Get the interface name from command line arguments 46 | const char *ifname = argv[1]; 47 | 48 | // Now we create a new socket endpoint for communication 49 | // Args: domain, type, protocol 50 | // returns a file descriptor 51 | if((fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { 52 | perror("Error while opening socket"); 53 | return -2; 54 | } 55 | 56 | // Here we pass the ifreq structure to ioctl 57 | strcpy(ifr.ifr_name, ifname); 58 | ioctl(fd, SIOCGIFINDEX, &ifr); 59 | 60 | // Set address family and network interface index of CAN socket 61 | addr.can_family = AF_CAN; 62 | addr.can_ifindex = ifr.ifr_ifindex; 63 | 64 | // Print the name of the interface and the index 65 | printf("%s at index %d\n", ifname, ifr.ifr_ifindex); 66 | 67 | // Bind the file descriptor name to the socket 68 | if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 69 | perror("Error in socket bind"); 70 | return -3; 71 | } 72 | 73 | while(1) 74 | { 75 | // Write the data to the CAN bus and record the number of bytes written 76 | bytes_read = read(fd, &frame, sizeof(struct can_frame)); 77 | 78 | printf("Read %d bytes\n", bytes_read); 79 | printf("CAN ID: %x \n", frame.can_id); 80 | printf("CAN DLC: %d \n", frame.can_dlc); 81 | printf("CAN DATA: \n"); 82 | for (i = 0; i < frame.can_dlc; i++) 83 | { 84 | printf("%x ", frame.data[i]); 85 | } 86 | printf("\n"); 87 | } 88 | 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /Code_Examples/socketCAN/SendRawPacket.c: -------------------------------------------------------------------------------- 1 | // Code to test sending manual messages over a virtual can interface 2 | 3 | // Use these headers to communicate with a raw can data frame 4 | #include 5 | #include 6 | 7 | // Additional socket stuff needed by the socketCAN library 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | // And finally, the regular c types for having some fun! 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | int fd; //file descriptor for reading and writing 22 | int bytes_transferred; //number of bytes sent over CAN 23 | 24 | // structure for CAN sockets includes: 25 | // address family, interface index, specific address info 26 | struct sockaddr_can addr; 27 | 28 | // structure for an individual frame in CAN 29 | struct can_frame frame; 30 | 31 | // Linux supports some standard ioctls to configure network devices. 32 | // They can be used on any socket's file descriptor regardless of the 33 | // family or type. Most of them pass an ifreq structure: 34 | struct ifreq ifr; 35 | 36 | // Check to make sure we have entered a CAN interface to use 37 | if (argc < 2) 38 | { 39 | printf("Please enter CAN bus to write to (ex: vcan0)\n"); 40 | printf("Args: Canbus\n"); 41 | return -1; 42 | } 43 | 44 | // Get the interface name from command line arguments 45 | const char *ifname = argv[1]; 46 | 47 | // Now we create a new socket endpoint for communication 48 | // Args: domain, type, protocol 49 | // returns a file descriptor 50 | if((fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { 51 | perror("Error while opening socket"); 52 | return -2; 53 | } 54 | 55 | // Here we pass the ifreq structure to ioctl 56 | strcpy(ifr.ifr_name, ifname); 57 | ioctl(fd, SIOCGIFINDEX, &ifr); 58 | 59 | // Set address family and network interface index of CAN socket 60 | addr.can_family = AF_CAN; 61 | addr.can_ifindex = ifr.ifr_ifindex; 62 | 63 | // Print the name of the interface and the index 64 | printf("%s at index %d\n", ifname, ifr.ifr_ifindex); 65 | 66 | // Bind the file descriptor name to the socket 67 | if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 68 | perror("Error in socket bind"); 69 | return -3; 70 | } 71 | 72 | // Setup the can frame with the correct ID, DLC, and values 73 | frame.can_id = 0x123; // 32-bit CAN_ID + EFF/RTR/ERR flags 74 | frame.can_dlc = 8; //data length code - we want 8 bytes here (the MAX!) 75 | frame.data[0] = 0xde; //first data byte 76 | frame.data[1] = 0xad; //second data byte 77 | frame.data[2] = 0xbe; //third data byte 78 | frame.data[3] = 0xef; //fourth data byte ... 79 | frame.data[4] = 0x12; 80 | frame.data[5] = 0x34; 81 | frame.data[6] = 0x56; 82 | frame.data[7] = 0x78; 83 | 84 | // Write the data to the CAN bus and record the number of bytes written 85 | bytes_transferred = write(fd, &frame, sizeof(struct can_frame)); 86 | 87 | printf("Wrote %d bytes\n", bytes_transferred); 88 | 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /Code_Examples/tty/Makefile: -------------------------------------------------------------------------------- 1 | # Comment/uncomment the following line to disable/enable debugging 2 | #DEBUG = y 3 | 4 | 5 | # Add your debugging flag (or not) to CFLAGS 6 | ifeq ($(DEBUG),y) 7 | DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 8 | else 9 | DEBFLAGS = -O2 10 | endif 11 | 12 | EXTRA_CFLAGS += $(DEBFLAGS) 13 | EXTRA_CFLAGS += -I.. 14 | 15 | ifneq ($(KERNELRELEASE),) 16 | # call from kernel build system 17 | 18 | obj-m := tiny_tty.o tiny_serial.o 19 | 20 | else 21 | 22 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 23 | PWD := $(shell pwd) 24 | 25 | default: 26 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 27 | 28 | endif 29 | 30 | 31 | 32 | clean: 33 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions 34 | 35 | depend .depend dep: 36 | $(CC) $(EXTRA_CFLAGS) -M *.c > .depend 37 | 38 | 39 | ifeq (.depend,$(wildcard .depend)) 40 | include .depend 41 | endif 42 | -------------------------------------------------------------------------------- /Code_Examples/tty/README.md: -------------------------------------------------------------------------------- 1 | # Why are these here? 2 | 3 | I added the tty drivers from the sample repos with some slight modifications to make them run better. I made the device major number dynamic and added a close method to the serial version. 4 | 5 | ### Current Bugs 6 | 7 | If you insert the tty driver, then remove it, then try to reinsert it there will be an error because it still doesn't clean itself up properly. You should be able to use it on the first try though. See my book notes on tty drivers for some more details. 8 | -------------------------------------------------------------------------------- /Code_Examples/tty/tiny_serial.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny Serial driver 3 | * 4 | * Copyright (C) 2002-2004 Greg Kroah-Hartman (greg@kroah.com) 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, version 2 of the License. 9 | * 10 | * This driver shows how to create a minimal serial driver. It does not rely on 11 | * any backing hardware, but creates a timer that emulates data being received 12 | * from some kind of hardware. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #define DRIVER_AUTHOR "Greg Kroah-Hartman " 27 | #define DRIVER_DESC "Tiny serial driver" 28 | 29 | /* Module information */ 30 | MODULE_AUTHOR( DRIVER_AUTHOR ); 31 | MODULE_DESCRIPTION( DRIVER_DESC ); 32 | MODULE_LICENSE("GPL"); 33 | 34 | #define DELAY_TIME HZ * 2 /* 2 seconds per character */ 35 | #define TINY_DATA_CHARACTER 't' 36 | 37 | #define TINY_SERIAL_MAJOR 0 /* experimental range */ 38 | #define TINY_SERIAL_MINORS 1 /* only have one minor */ 39 | #define UART_NR 1 /* only use one port */ 40 | 41 | #define TINY_SERIAL_NAME "ttytiny" 42 | 43 | #define MY_NAME TINY_SERIAL_NAME 44 | 45 | static struct timer_list *timer; 46 | 47 | static void tiny_stop_tx(struct uart_port *port) 48 | { 49 | } 50 | 51 | static void tiny_stop_rx(struct uart_port *port) 52 | { 53 | } 54 | 55 | static void tiny_enable_ms(struct uart_port *port) 56 | { 57 | } 58 | 59 | static void tiny_tx_chars(struct uart_port *port) 60 | { 61 | struct circ_buf *xmit = &port->state->xmit; 62 | int count; 63 | 64 | if (port->x_char) { 65 | pr_debug("wrote %2x", port->x_char); 66 | port->icount.tx++; 67 | port->x_char = 0; 68 | return; 69 | } 70 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { 71 | tiny_stop_tx(port); 72 | return; 73 | } 74 | 75 | count = port->fifosize >> 1; 76 | do { 77 | pr_debug("wrote %2x", xmit->buf[xmit->tail]); 78 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 79 | port->icount.tx++; 80 | if (uart_circ_empty(xmit)) 81 | break; 82 | } while (--count > 0); 83 | 84 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 85 | uart_write_wakeup(port); 86 | 87 | if (uart_circ_empty(xmit)) 88 | tiny_stop_tx(port); 89 | } 90 | 91 | static void tiny_start_tx(struct uart_port *port) 92 | { 93 | } 94 | 95 | static void tiny_timer(unsigned long data) 96 | { 97 | struct uart_port *port; 98 | struct tty_struct *tty; 99 | struct tty_port *tty_port; 100 | 101 | 102 | port = (struct uart_port *)data; 103 | if (!port) 104 | return; 105 | if (!port->state) 106 | return; 107 | tty = port->state->port.tty; 108 | if (!tty) 109 | return; 110 | 111 | tty_port = tty->port; 112 | 113 | /* add one character to the tty port */ 114 | /* this doesn't actually push the data through unless tty->low_latency is set */ 115 | tty_insert_flip_char(tty_port, TINY_DATA_CHARACTER, 0); 116 | 117 | tty_flip_buffer_push(tty_port); 118 | 119 | /* resubmit the timer again */ 120 | timer->expires = jiffies + DELAY_TIME; 121 | add_timer(timer); 122 | 123 | /* see if we have any data to transmit */ 124 | tiny_tx_chars(port); 125 | } 126 | 127 | static unsigned int tiny_tx_empty(struct uart_port *port) 128 | { 129 | return 0; 130 | } 131 | 132 | static unsigned int tiny_get_mctrl(struct uart_port *port) 133 | { 134 | return 0; 135 | } 136 | 137 | static void tiny_set_mctrl(struct uart_port *port, unsigned int mctrl) 138 | { 139 | } 140 | 141 | static void tiny_break_ctl(struct uart_port *port, int break_state) 142 | { 143 | } 144 | 145 | static void tiny_set_termios(struct uart_port *port, 146 | struct ktermios *new, struct ktermios *old) 147 | { 148 | int baud, quot, cflag = new->c_cflag; 149 | /* get the byte size */ 150 | switch (cflag & CSIZE) { 151 | case CS5: 152 | printk(KERN_DEBUG " - data bits = 5\n"); 153 | break; 154 | case CS6: 155 | printk(KERN_DEBUG " - data bits = 6\n"); 156 | break; 157 | case CS7: 158 | printk(KERN_DEBUG " - data bits = 7\n"); 159 | break; 160 | default: // CS8 161 | printk(KERN_DEBUG " - data bits = 8\n"); 162 | break; 163 | } 164 | 165 | /* determine the parity */ 166 | if (cflag & PARENB) 167 | if (cflag & PARODD) 168 | pr_debug(" - parity = odd\n"); 169 | else 170 | pr_debug(" - parity = even\n"); 171 | else 172 | pr_debug(" - parity = none\n"); 173 | 174 | /* figure out the stop bits requested */ 175 | if (cflag & CSTOPB) 176 | pr_debug(" - stop bits = 2\n"); 177 | else 178 | pr_debug(" - stop bits = 1\n"); 179 | 180 | /* figure out the flow control settings */ 181 | if (cflag & CRTSCTS) 182 | pr_debug(" - RTS/CTS is enabled\n"); 183 | else 184 | pr_debug(" - RTS/CTS is disabled\n"); 185 | 186 | /* Set baud rate */ 187 | baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16); 188 | quot = uart_get_divisor(port, baud); 189 | 190 | //UART_PUT_DIV_LO(port, (quot & 0xff)); 191 | //UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8)); 192 | } 193 | 194 | static int tiny_startup(struct uart_port *port) 195 | { 196 | /* this is the first time this port is opened */ 197 | /* do any hardware initialization needed here */ 198 | 199 | /* create our timer and submit it */ 200 | if (!timer) { 201 | timer = kmalloc(sizeof(*timer), GFP_KERNEL); 202 | if (!timer) 203 | return -ENOMEM; 204 | } 205 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) 206 | timer->data = (unsigned long)port; 207 | timer->function = tiny_timer; 208 | #else 209 | timer_setup(timer, (void *) tiny_timer, (unsigned long) port); 210 | timer->function = (void *) tiny_timer; 211 | #endif 212 | timer->expires = jiffies + DELAY_TIME; 213 | add_timer(timer); 214 | return 0; 215 | } 216 | 217 | static void tiny_shutdown(struct uart_port *port) 218 | { 219 | /* The port is being closed by the last user. */ 220 | /* Do any hardware specific stuff here */ 221 | 222 | /* shut down our timer */ 223 | del_timer(timer); 224 | } 225 | 226 | static const char *tiny_type(struct uart_port *port) 227 | { 228 | return "tinytty"; 229 | } 230 | 231 | static void tiny_release_port(struct uart_port *port) 232 | { 233 | 234 | } 235 | 236 | static int tiny_request_port(struct uart_port *port) 237 | { 238 | return 0; 239 | } 240 | 241 | static void tiny_config_port(struct uart_port *port, int flags) 242 | { 243 | } 244 | 245 | static int tiny_verify_port(struct uart_port *port, struct serial_struct *ser) 246 | { 247 | return 0; 248 | } 249 | 250 | static struct uart_ops tiny_ops = { 251 | .tx_empty = tiny_tx_empty, 252 | .set_mctrl = tiny_set_mctrl, 253 | .get_mctrl = tiny_get_mctrl, 254 | .stop_tx = tiny_stop_tx, 255 | .start_tx = tiny_start_tx, 256 | .stop_rx = tiny_stop_rx, 257 | .enable_ms = tiny_enable_ms, 258 | .break_ctl = tiny_break_ctl, 259 | .startup = tiny_startup, 260 | .shutdown = tiny_shutdown, 261 | .set_termios = tiny_set_termios, 262 | .type = tiny_type, 263 | .release_port = tiny_release_port, 264 | .request_port = tiny_request_port, 265 | .config_port = tiny_config_port, 266 | .verify_port = tiny_verify_port, 267 | }; 268 | 269 | static struct uart_port tiny_port = { 270 | .ops = &tiny_ops, 271 | }; 272 | 273 | static struct uart_driver tiny_reg = { 274 | .owner = THIS_MODULE, 275 | .driver_name = TINY_SERIAL_NAME, 276 | .dev_name = TINY_SERIAL_NAME, 277 | .major = TINY_SERIAL_MAJOR, 278 | .minor = TINY_SERIAL_MINORS, 279 | .nr = UART_NR, 280 | }; 281 | 282 | static int __init tiny_init(void) 283 | { 284 | int result; 285 | 286 | printk(KERN_INFO "Tiny serial driver loaded\n"); 287 | 288 | result = uart_register_driver(&tiny_reg); 289 | if (result) 290 | return result; 291 | 292 | result = uart_add_one_port(&tiny_reg, &tiny_port); 293 | if (result) 294 | uart_unregister_driver(&tiny_reg); 295 | 296 | return result; 297 | } 298 | 299 | static void __exit tiny_exit(void) 300 | { 301 | uart_remove_one_port(&tiny_reg, &tiny_port); 302 | uart_unregister_driver(&tiny_reg); 303 | } 304 | 305 | module_init(tiny_init); 306 | module_exit(tiny_exit); 307 | -------------------------------------------------------------------------------- /Code_Examples/tty/tiny_tty.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny TTY driver 3 | * 4 | * Copyright (C) 2002-2004 Greg Kroah-Hartman (greg@kroah.com) 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, version 2 of the License. 9 | * 10 | * This driver shows how to create a minimal tty driver. It does not rely on 11 | * any backing hardware, but creates a timer that emulates data being received 12 | * from some kind of hardware. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #define DRIVER_VERSION "v2.0" 31 | #define DRIVER_AUTHOR "Greg Kroah-Hartman " 32 | #define DRIVER_DESC "Tiny TTY driver" 33 | 34 | /* Module information */ 35 | MODULE_AUTHOR(DRIVER_AUTHOR); 36 | MODULE_DESCRIPTION(DRIVER_DESC); 37 | MODULE_LICENSE("GPL"); 38 | 39 | #define DELAY_TIME (HZ * 2) /* 2 seconds per character */ 40 | #define TINY_DATA_CHARACTER 't' 41 | 42 | #define TINY_TTY_MAJOR 0 /* experimental range */ 43 | #define TINY_TTY_MINORS 4 /* only have 4 devices */ 44 | 45 | struct tiny_serial { 46 | struct tty_struct *tty; /* pointer to the tty for this device */ 47 | int open_count; /* number of times this port has been opened */ 48 | struct mutex mutex; /* locks this structure */ 49 | struct timer_list timer; 50 | 51 | /* for tiocmget and tiocmset functions */ 52 | int msr; /* MSR shadow */ 53 | int mcr; /* MCR shadow */ 54 | 55 | /* for ioctl fun */ 56 | struct serial_struct serial; 57 | wait_queue_head_t wait; 58 | struct async_icount icount; 59 | }; 60 | 61 | static struct tiny_serial *tiny_table[TINY_TTY_MINORS]; /* initially all NULL */ 62 | static struct tty_port tiny_tty_port[TINY_TTY_MINORS]; 63 | 64 | 65 | static void tiny_timer(struct timer_list *t) 66 | { 67 | struct tiny_serial *tiny = from_timer(tiny, t, timer); 68 | struct tty_struct *tty; 69 | struct tty_port *port; 70 | int i; 71 | char data[1] = {TINY_DATA_CHARACTER}; 72 | int data_size = 1; 73 | 74 | if (!tiny) 75 | return; 76 | 77 | tty = tiny->tty; 78 | port = tty->port; 79 | 80 | /* send the data to the tty layer for users to read. This doesn't 81 | * actually push the data through unless tty->low_latency is set */ 82 | for (i = 0; i < data_size; ++i) { 83 | if (!tty_buffer_request_room(port, 1)) 84 | tty_flip_buffer_push(port); 85 | tty_insert_flip_char(port, data[i], TTY_NORMAL); 86 | } 87 | tty_flip_buffer_push(port); 88 | 89 | /* resubmit the timer again */ 90 | tiny->timer.expires = jiffies + DELAY_TIME; 91 | add_timer(&tiny->timer); 92 | } 93 | 94 | static int tiny_open(struct tty_struct *tty, struct file *file) 95 | { 96 | struct tiny_serial *tiny; 97 | int index; 98 | 99 | /* initialize the pointer in case something fails */ 100 | tty->driver_data = NULL; 101 | 102 | /* get the serial object associated with this tty pointer */ 103 | index = tty->index; 104 | tiny = tiny_table[index]; 105 | if (tiny == NULL) { 106 | /* first time accessing this device, let's create it */ 107 | tiny = kmalloc(sizeof(*tiny), GFP_KERNEL); 108 | if (!tiny) 109 | return -ENOMEM; 110 | 111 | mutex_init(&tiny->mutex); 112 | tiny->open_count = 0; 113 | 114 | tiny_table[index] = tiny; 115 | } 116 | 117 | mutex_lock(&tiny->mutex); 118 | 119 | /* save our structure within the tty structure */ 120 | tty->driver_data = tiny; 121 | tiny->tty = tty; 122 | 123 | ++tiny->open_count; 124 | if (tiny->open_count == 1) { 125 | /* this is the first time this port is opened */ 126 | /* do any hardware initialization needed here */ 127 | 128 | /* create our timer and submit it */ 129 | timer_setup(&tiny->timer, tiny_timer, 0); 130 | tiny->timer.expires = jiffies + DELAY_TIME; 131 | add_timer(&tiny->timer); 132 | } 133 | 134 | mutex_unlock(&tiny->mutex); 135 | return 0; 136 | } 137 | 138 | static void do_close(struct tiny_serial *tiny) 139 | { 140 | mutex_lock(&tiny->mutex); 141 | 142 | if (!tiny->open_count) { 143 | /* port was never opened */ 144 | goto exit; 145 | } 146 | 147 | --tiny->open_count; 148 | if (tiny->open_count <= 0) { 149 | /* The port is being closed by the last user. */ 150 | /* Do any hardware specific stuff here */ 151 | 152 | /* shut down our timer */ 153 | del_timer(&tiny->timer); 154 | } 155 | exit: 156 | mutex_unlock(&tiny->mutex); 157 | } 158 | 159 | static void tiny_close(struct tty_struct *tty, struct file *file) 160 | { 161 | struct tiny_serial *tiny = tty->driver_data; 162 | 163 | if (tiny) 164 | do_close(tiny); 165 | } 166 | 167 | static int tiny_write(struct tty_struct *tty, 168 | const unsigned char *buffer, int count) 169 | { 170 | struct tiny_serial *tiny = tty->driver_data; 171 | int i; 172 | int retval = -EINVAL; 173 | 174 | if (!tiny) 175 | return -ENODEV; 176 | 177 | mutex_lock(&tiny->mutex); 178 | 179 | if (!tiny->open_count) 180 | /* port was not opened */ 181 | goto exit; 182 | 183 | /* fake sending the data out a hardware port by 184 | * writing it to the kernel debug log. 185 | */ 186 | pr_debug("%s - ", __func__); 187 | for (i = 0; i < count; ++i) 188 | pr_info("%02x ", buffer[i]); 189 | pr_info("\n"); 190 | 191 | exit: 192 | mutex_unlock(&tiny->mutex); 193 | return retval; 194 | } 195 | 196 | static int tiny_write_room(struct tty_struct *tty) 197 | { 198 | struct tiny_serial *tiny = tty->driver_data; 199 | int room = -EINVAL; 200 | 201 | if (!tiny) 202 | return -ENODEV; 203 | 204 | mutex_lock(&tiny->mutex); 205 | 206 | if (!tiny->open_count) { 207 | /* port was not opened */ 208 | goto exit; 209 | } 210 | 211 | /* calculate how much room is left in the device */ 212 | room = 255; 213 | 214 | exit: 215 | mutex_unlock(&tiny->mutex); 216 | return room; 217 | } 218 | 219 | #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) 220 | 221 | static void tiny_set_termios(struct tty_struct *tty, struct ktermios *old_termios) 222 | { 223 | unsigned int cflag; 224 | 225 | cflag = tty->termios.c_cflag; 226 | 227 | /* check that they really want us to change something */ 228 | if (old_termios) { 229 | if ((cflag == old_termios->c_cflag) && 230 | (RELEVANT_IFLAG(tty->termios.c_iflag) == 231 | RELEVANT_IFLAG(old_termios->c_iflag))) { 232 | pr_debug(" - nothing to change...\n"); 233 | return; 234 | } 235 | } 236 | 237 | /* get the byte size */ 238 | switch (cflag & CSIZE) { 239 | case CS5: 240 | pr_debug(" - data bits = 5\n"); 241 | break; 242 | case CS6: 243 | pr_debug(" - data bits = 6\n"); 244 | break; 245 | case CS7: 246 | pr_debug(" - data bits = 7\n"); 247 | break; 248 | default: 249 | case CS8: 250 | pr_debug(" - data bits = 8\n"); 251 | break; 252 | } 253 | 254 | /* determine the parity */ 255 | if (cflag & PARENB) 256 | if (cflag & PARODD) 257 | pr_debug(" - parity = odd\n"); 258 | else 259 | pr_debug(" - parity = even\n"); 260 | else 261 | pr_debug(" - parity = none\n"); 262 | 263 | /* figure out the stop bits requested */ 264 | if (cflag & CSTOPB) 265 | pr_debug(" - stop bits = 2\n"); 266 | else 267 | pr_debug(" - stop bits = 1\n"); 268 | 269 | /* figure out the hardware flow control settings */ 270 | if (cflag & CRTSCTS) 271 | pr_debug(" - RTS/CTS is enabled\n"); 272 | else 273 | pr_debug(" - RTS/CTS is disabled\n"); 274 | 275 | /* determine software flow control */ 276 | /* if we are implementing XON/XOFF, set the start and 277 | * stop character in the device */ 278 | if (I_IXOFF(tty) || I_IXON(tty)) { 279 | unsigned char stop_char = STOP_CHAR(tty); 280 | unsigned char start_char = START_CHAR(tty); 281 | 282 | /* if we are implementing INBOUND XON/XOFF */ 283 | if (I_IXOFF(tty)) 284 | pr_debug(" - INBOUND XON/XOFF is enabled, " 285 | "XON = %2x, XOFF = %2x", start_char, stop_char); 286 | else 287 | pr_debug(" - INBOUND XON/XOFF is disabled"); 288 | 289 | /* if we are implementing OUTBOUND XON/XOFF */ 290 | if (I_IXON(tty)) 291 | pr_debug(" - OUTBOUND XON/XOFF is enabled, " 292 | "XON = %2x, XOFF = %2x", start_char, stop_char); 293 | else 294 | pr_debug(" - OUTBOUND XON/XOFF is disabled"); 295 | } 296 | 297 | /* get the baud rate wanted */ 298 | pr_debug(" - baud rate = %d", tty_get_baud_rate(tty)); 299 | } 300 | 301 | /* Our fake UART values */ 302 | #define MCR_DTR 0x01 303 | #define MCR_RTS 0x02 304 | #define MCR_LOOP 0x04 305 | #define MSR_CTS 0x08 306 | #define MSR_CD 0x10 307 | #define MSR_RI 0x20 308 | #define MSR_DSR 0x40 309 | 310 | static int tiny_tiocmget(struct tty_struct *tty) 311 | { 312 | struct tiny_serial *tiny = tty->driver_data; 313 | 314 | unsigned int result = 0; 315 | unsigned int msr = tiny->msr; 316 | unsigned int mcr = tiny->mcr; 317 | 318 | result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | /* DTR is set */ 319 | ((mcr & MCR_RTS) ? TIOCM_RTS : 0) | /* RTS is set */ 320 | ((mcr & MCR_LOOP) ? TIOCM_LOOP : 0) | /* LOOP is set */ 321 | ((msr & MSR_CTS) ? TIOCM_CTS : 0) | /* CTS is set */ 322 | ((msr & MSR_CD) ? TIOCM_CAR : 0) | /* Carrier detect is set*/ 323 | ((msr & MSR_RI) ? TIOCM_RI : 0) | /* Ring Indicator is set */ 324 | ((msr & MSR_DSR) ? TIOCM_DSR : 0); /* DSR is set */ 325 | 326 | return result; 327 | } 328 | 329 | static int tiny_tiocmset(struct tty_struct *tty, unsigned int set, 330 | unsigned int clear) 331 | { 332 | struct tiny_serial *tiny = tty->driver_data; 333 | unsigned int mcr = tiny->mcr; 334 | 335 | if (set & TIOCM_RTS) 336 | mcr |= MCR_RTS; 337 | if (set & TIOCM_DTR) 338 | mcr |= MCR_RTS; 339 | 340 | if (clear & TIOCM_RTS) 341 | mcr &= ~MCR_RTS; 342 | if (clear & TIOCM_DTR) 343 | mcr &= ~MCR_RTS; 344 | 345 | /* set the new MCR value in the device */ 346 | tiny->mcr = mcr; 347 | return 0; 348 | } 349 | 350 | static int tiny_proc_show(struct seq_file *m, void *v) 351 | { 352 | struct tiny_serial *tiny; 353 | int i; 354 | 355 | seq_printf(m, "tinyserinfo:1.0 driver:%s\n", DRIVER_VERSION); 356 | for (i = 0; i < TINY_TTY_MINORS; ++i) { 357 | tiny = tiny_table[i]; 358 | if (tiny == NULL) 359 | continue; 360 | 361 | seq_printf(m, "%d\n", i); 362 | } 363 | 364 | return 0; 365 | } 366 | 367 | #define tiny_ioctl tiny_ioctl_tiocgserial 368 | static int tiny_ioctl(struct tty_struct *tty, unsigned int cmd, 369 | unsigned long arg) 370 | { 371 | struct tiny_serial *tiny = tty->driver_data; 372 | 373 | if (cmd == TIOCGSERIAL) { 374 | struct serial_struct tmp; 375 | 376 | if (!arg) 377 | return -EFAULT; 378 | 379 | memset(&tmp, 0, sizeof(tmp)); 380 | 381 | tmp.type = tiny->serial.type; 382 | tmp.line = tiny->serial.line; 383 | tmp.port = tiny->serial.port; 384 | tmp.irq = tiny->serial.irq; 385 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; 386 | tmp.xmit_fifo_size = tiny->serial.xmit_fifo_size; 387 | tmp.baud_base = tiny->serial.baud_base; 388 | tmp.close_delay = 5*HZ; 389 | tmp.closing_wait = 30*HZ; 390 | tmp.custom_divisor = tiny->serial.custom_divisor; 391 | tmp.hub6 = tiny->serial.hub6; 392 | tmp.io_type = tiny->serial.io_type; 393 | 394 | if (copy_to_user((void __user *)arg, &tmp, sizeof(struct serial_struct))) 395 | return -EFAULT; 396 | return 0; 397 | } 398 | return -ENOIOCTLCMD; 399 | } 400 | #undef tiny_ioctl 401 | 402 | #define tiny_ioctl tiny_ioctl_tiocmiwait 403 | static int tiny_ioctl(struct tty_struct *tty, unsigned int cmd, 404 | unsigned long arg) 405 | { 406 | struct tiny_serial *tiny = tty->driver_data; 407 | 408 | if (cmd == TIOCMIWAIT) { 409 | DECLARE_WAITQUEUE(wait, current); 410 | struct async_icount cnow; 411 | struct async_icount cprev; 412 | 413 | cprev = tiny->icount; 414 | while (1) { 415 | add_wait_queue(&tiny->wait, &wait); 416 | set_current_state(TASK_INTERRUPTIBLE); 417 | schedule(); 418 | remove_wait_queue(&tiny->wait, &wait); 419 | 420 | /* see if a signal woke us up */ 421 | if (signal_pending(current)) 422 | return -ERESTARTSYS; 423 | 424 | cnow = tiny->icount; 425 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 426 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) 427 | return -EIO; /* no change => error */ 428 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || 429 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || 430 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || 431 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { 432 | return 0; 433 | } 434 | cprev = cnow; 435 | } 436 | 437 | } 438 | return -ENOIOCTLCMD; 439 | } 440 | #undef tiny_ioctl 441 | 442 | #define tiny_ioctl tiny_ioctl_tiocgicount 443 | static int tiny_ioctl(struct tty_struct *tty, unsigned int cmd, 444 | unsigned long arg) 445 | { 446 | struct tiny_serial *tiny = tty->driver_data; 447 | 448 | if (cmd == TIOCGICOUNT) { 449 | struct async_icount cnow = tiny->icount; 450 | struct serial_icounter_struct icount; 451 | 452 | icount.cts = cnow.cts; 453 | icount.dsr = cnow.dsr; 454 | icount.rng = cnow.rng; 455 | icount.dcd = cnow.dcd; 456 | icount.rx = cnow.rx; 457 | icount.tx = cnow.tx; 458 | icount.frame = cnow.frame; 459 | icount.overrun = cnow.overrun; 460 | icount.parity = cnow.parity; 461 | icount.brk = cnow.brk; 462 | icount.buf_overrun = cnow.buf_overrun; 463 | 464 | if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) 465 | return -EFAULT; 466 | return 0; 467 | } 468 | return -ENOIOCTLCMD; 469 | } 470 | #undef tiny_ioctl 471 | 472 | /* the real tiny_ioctl function. The above is done to get the small functions in the book */ 473 | static int tiny_ioctl(struct tty_struct *tty, unsigned int cmd, 474 | unsigned long arg) 475 | { 476 | switch (cmd) { 477 | case TIOCGSERIAL: 478 | return tiny_ioctl_tiocgserial(tty, cmd, arg); 479 | case TIOCMIWAIT: 480 | return tiny_ioctl_tiocmiwait(tty, cmd, arg); 481 | case TIOCGICOUNT: 482 | return tiny_ioctl_tiocgicount(tty, cmd, arg); 483 | } 484 | 485 | return -ENOIOCTLCMD; 486 | } 487 | 488 | 489 | static const struct tty_operations serial_ops = { 490 | .open = tiny_open, 491 | .close = tiny_close, 492 | .write = tiny_write, 493 | .write_room = tiny_write_room, 494 | .set_termios = tiny_set_termios, 495 | .proc_show = tiny_proc_show, 496 | .tiocmget = tiny_tiocmget, 497 | .tiocmset = tiny_tiocmset, 498 | .ioctl = tiny_ioctl, 499 | }; 500 | 501 | static struct tty_driver *tiny_tty_driver; 502 | 503 | static int __init tiny_init(void) 504 | { 505 | int retval; 506 | int i; 507 | 508 | /* allocate the tty driver */ 509 | tiny_tty_driver = alloc_tty_driver(TINY_TTY_MINORS); 510 | if (!tiny_tty_driver) 511 | return -ENOMEM; 512 | 513 | /* initialize the tty driver */ 514 | tiny_tty_driver->owner = THIS_MODULE; 515 | tiny_tty_driver->driver_name = "tiny_tty"; 516 | tiny_tty_driver->name = "ttty"; 517 | tiny_tty_driver->major = TINY_TTY_MAJOR, 518 | tiny_tty_driver->type = TTY_DRIVER_TYPE_SERIAL, 519 | tiny_tty_driver->subtype = SERIAL_TYPE_NORMAL, 520 | tiny_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV, 521 | tiny_tty_driver->init_termios = tty_std_termios; 522 | tiny_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; 523 | tty_set_operations(tiny_tty_driver, &serial_ops); 524 | for (i = 0; i < TINY_TTY_MINORS; i++) { 525 | tty_port_init(tiny_tty_port + i); 526 | tty_port_link_device(tiny_tty_port + i, tiny_tty_driver, i); 527 | } 528 | 529 | /* register the tty driver */ 530 | retval = tty_register_driver(tiny_tty_driver); 531 | if (retval) { 532 | pr_err("failed to register tiny tty driver"); 533 | put_tty_driver(tiny_tty_driver); 534 | return retval; 535 | } 536 | 537 | for (i = 0; i < TINY_TTY_MINORS; ++i) 538 | tty_register_device(tiny_tty_driver, i, NULL); 539 | 540 | pr_info(DRIVER_DESC " " DRIVER_VERSION); 541 | return retval; 542 | } 543 | 544 | static void __exit tiny_exit(void) 545 | { 546 | struct tiny_serial *tiny; 547 | int i; 548 | 549 | for (i = 0; i < TINY_TTY_MINORS; ++i) 550 | tty_unregister_device(tiny_tty_driver, i); 551 | tty_unregister_driver(tiny_tty_driver); 552 | 553 | /* shut down all of the timers and free the memory */ 554 | for (i = 0; i < TINY_TTY_MINORS; ++i) { 555 | tiny = tiny_table[i]; 556 | if (tiny) { 557 | /* close the port */ 558 | while (tiny->open_count) 559 | do_close(tiny); 560 | 561 | /* shut down our timer and free the memory */ 562 | del_timer(&tiny->timer); 563 | kfree(tiny); 564 | tiny_table[i] = NULL; 565 | } 566 | } 567 | } 568 | 569 | module_init(tiny_init); 570 | module_exit(tiny_exit); 571 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LDD3-Notes 2 | Notes on the book Linux Device Drivers, 3rd Edition, by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman. My notes from this book will attempt to add updated information for Linux 5.x. 3 | 4 | Each chapter in the book is covered in detail in this note set. There is also a folder with example code to run some fun drivers as examples. See additional folders for more details. 5 | --------------------------------------------------------------------------------