1 | -------------
|
---|
2 | MDEV Primer
|
---|
3 | -------------
|
---|
4 |
|
---|
5 | For those of us who know how to use mdev, a primer might seem lame. For
|
---|
6 | everyone else, mdev is a weird black box that they hear is awesome, but can't
|
---|
7 | seem to get their head around how it works. Thus, a primer.
|
---|
8 |
|
---|
9 | -----------
|
---|
10 | Basic Use
|
---|
11 | -----------
|
---|
12 |
|
---|
13 | Mdev has two primary uses: initial population and dynamic updates. Both
|
---|
14 | require sysfs support in the kernel and have it mounted at /sys. For dynamic
|
---|
15 | updates, you also need to have hotplugging enabled in your kernel.
|
---|
16 |
|
---|
17 | Here's a typical code snippet from the init script:
|
---|
18 | [0] mount -t proc proc /proc
|
---|
19 | [1] mount -t sysfs sysfs /sys
|
---|
20 | [2] echo /sbin/mdev > /proc/sys/kernel/hotplug
|
---|
21 | [3] mdev -s
|
---|
22 |
|
---|
23 | Alternatively, without procfs the above becomes:
|
---|
24 | [1] mount -t sysfs sysfs /sys
|
---|
25 | [2] sysctl -w kernel.hotplug=/sbin/mdev
|
---|
26 | [3] mdev -s
|
---|
27 |
|
---|
28 |
|
---|
29 | Of course, a more "full" setup would entail executing this before the previous
|
---|
30 | code snippet:
|
---|
31 | [4] mount -t tmpfs -o size=64k,mode=0755 tmpfs /dev
|
---|
32 | [5] mkdir /dev/pts
|
---|
33 | [6] mount -t devpts devpts /dev/pts
|
---|
34 |
|
---|
35 | The simple explanation here is that [1] you need to have /sys mounted before
|
---|
36 | executing mdev. Then you [2] instruct the kernel to execute /sbin/mdev whenever
|
---|
37 | a device is added or removed so that the device node can be created or
|
---|
38 | destroyed. Then you [3] seed /dev with all the device nodes that were created
|
---|
39 | while the system was booting.
|
---|
40 |
|
---|
41 | For the "full" setup, you want to [4] make sure /dev is a tmpfs filesystem
|
---|
42 | (assuming you're running out of flash). Then you want to [5] create the
|
---|
43 | /dev/pts mount point and finally [6] mount the devpts filesystem on it.
|
---|
44 |
|
---|
45 | -------------
|
---|
46 | MDEV Config (/etc/mdev.conf)
|
---|
47 | -------------
|
---|
48 |
|
---|
49 | Mdev has an optional config file for controlling ownership/permissions of
|
---|
50 | device nodes if your system needs something more than the default root/root
|
---|
51 | 660 permissions.
|
---|
52 |
|
---|
53 | The file has the format:
|
---|
54 | [-][envmatch]<device regex> <uid>:<gid> <permissions>
|
---|
55 | or
|
---|
56 | [envmatch]@<maj[,min1[-min2]]> <uid>:<gid> <permissions>
|
---|
57 | or
|
---|
58 | $envvar=<regex> <uid>:<gid> <permissions>
|
---|
59 |
|
---|
60 | For example:
|
---|
61 | hd[a-z][0-9]* 0:3 660
|
---|
62 |
|
---|
63 | The config file parsing stops at the first matching line. If no line is
|
---|
64 | matched, then the default of 0:0 660 is used. To set your own default, simply
|
---|
65 | create your own total match like so:
|
---|
66 |
|
---|
67 | .* 1:1 777
|
---|
68 |
|
---|
69 | You can rename/move device nodes by using the next optional field.
|
---|
70 |
|
---|
71 | <device regex> <uid>:<gid> <permissions> [=path]
|
---|
72 |
|
---|
73 | So if you want to place the device node into a subdirectory, make sure the path
|
---|
74 | has a trailing /. If you want to rename the device node, just place the name.
|
---|
75 | hda 0:3 660 =drives/
|
---|
76 | This will move "hda" into the drives/ subdirectory.
|
---|
77 | hdb 0:3 660 =cdrom
|
---|
78 | This will rename "hdb" to "cdrom".
|
---|
79 |
|
---|
80 | Similarly, ">path" renames/moves the device but it also creates
|
---|
81 | a direct symlink /dev/DEVNAME to the renamed/moved device.
|
---|
82 |
|
---|
83 | You can also prevent creation of device nodes with the 4th field as "!":
|
---|
84 | tty[a-z]. 0:0 660 !
|
---|
85 | pty[a-z]. 0:0 660 !
|
---|
86 |
|
---|
87 | If you also enable support for executing your own commands, then the file has
|
---|
88 | the format:
|
---|
89 | <device regex> <uid>:<gid> <permissions> [=path] [@|$|*<command>]
|
---|
90 | or
|
---|
91 | <device regex> <uid>:<gid> <permissions> [>path] [@|$|*<command>]
|
---|
92 | or
|
---|
93 | <device regex> <uid>:<gid> <permissions> [!] [@|$|*<command>]
|
---|
94 |
|
---|
95 | For example:
|
---|
96 | ---8<---
|
---|
97 | # block devices
|
---|
98 | ([hs]d[a-z]) root:disk 660 >disk/%1/0
|
---|
99 | ([hs]d[a-z])([0-9]+) root:disk 660 >disk/%1/%2
|
---|
100 | mmcblk([0-9]+) root:disk 660 >disk/mmc/%1/0
|
---|
101 | mmcblk([0-9]+)p([0-9]+) root:disk 660 >disk/mmc/%1/%2
|
---|
102 | # network devices
|
---|
103 | (tun|tap) root:network 660 >net/%1
|
---|
104 | ---8<---
|
---|
105 |
|
---|
106 | The special characters have the meaning:
|
---|
107 | @ Run after creating the device.
|
---|
108 | $ Run before removing the device.
|
---|
109 | * Run both after creating and before removing the device.
|
---|
110 |
|
---|
111 | The command is executed via the system() function (which means you're giving a
|
---|
112 | command to the shell), so make sure you have a shell installed at /bin/sh. You
|
---|
113 | should also keep in mind that the kernel executes hotplug helpers with stdin,
|
---|
114 | stdout, and stderr connected to /dev/null.
|
---|
115 |
|
---|
116 | For your convenience, the shell env var $MDEV is set to the device name. So if
|
---|
117 | the device "hdc" was matched, MDEV would be set to "hdc".
|
---|
118 |
|
---|
119 | ----------
|
---|
120 | FIRMWARE
|
---|
121 | ----------
|
---|
122 |
|
---|
123 | Some kernel device drivers need to request firmware at runtime in order to
|
---|
124 | properly initialize a device. Place all such firmware files into the
|
---|
125 | /lib/firmware/ directory. At runtime, the kernel will invoke mdev with the
|
---|
126 | filename of the firmware which mdev will load out of /lib/firmware/ and into
|
---|
127 | the kernel via the sysfs interface. The exact filename is hardcoded in the
|
---|
128 | kernel, so look there if you need to know how to name the file in userspace.
|
---|
129 |
|
---|
130 | ------------
|
---|
131 | SEQUENCING
|
---|
132 | ------------
|
---|
133 |
|
---|
134 | Kernel does not serialize hotplug events. It increments SEQNUM environmental
|
---|
135 | variable for each successive hotplug invocation. Normally, mdev doesn't care.
|
---|
136 | This may reorder hotplug and hot-unplug events, with typical symptoms of
|
---|
137 | device nodes sometimes not created as expected.
|
---|
138 |
|
---|
139 | However, if /dev/mdev.seq file is found, mdev will compare its
|
---|
140 | contents with SEQNUM. It will retry up to two seconds, waiting for them
|
---|
141 | to match. If they match exactly (not even trailing '\n' is allowed),
|
---|
142 | or if two seconds pass, mdev runs as usual, then it rewrites /dev/mdev.seq
|
---|
143 | with SEQNUM+1.
|
---|
144 |
|
---|
145 | IOW: this will serialize concurrent mdev invocations.
|
---|
146 |
|
---|
147 | If you want to activate this feature, execute "echo >/dev/mdev.seq" prior to
|
---|
148 | setting mdev to be the hotplug handler. This writes single '\n' to the file.
|
---|
149 | NB: mdev recognizes /dev/mdev.seq consisting of single '\n' character
|
---|
150 | as a special case. IOW: this will not make your first hotplug event
|
---|
151 | to stall for two seconds.
|
---|