1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 20:07:36 +00:00

SystemServer: Create /dev/devctl and create devices based on its events

We first create the /dev/devctl based on the information from the SysFS.
Then, we create block devices and character devices based on the events
we read from that device.
This commit is contained in:
Liav A 2021-12-20 11:48:25 +02:00 committed by Linus Groh
parent eaad77b286
commit 4da7b543c6

View file

@ -9,6 +9,7 @@
#include <AK/Assertions.h> #include <AK/Assertions.h>
#include <AK/ByteBuffer.h> #include <AK/ByteBuffer.h>
#include <AK/Debug.h> #include <AK/Debug.h>
#include <Kernel/API/DeviceEvent.h>
#include <LibCore/ArgsParser.h> #include <LibCore/ArgsParser.h>
#include <LibCore/ConfigFile.h> #include <LibCore/ConfigFile.h>
#include <LibCore/DirIterator.h> #include <LibCore/DirIterator.h>
@ -132,45 +133,13 @@ static void create_devtmpfs_block_device(String name, mode_t mode, unsigned majo
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
static void populate_devtmpfs_block_devices()
{
Core::DirIterator di("/sys/dev/block/", Core::DirIterator::SkipParentAndBaseDir);
if (di.has_error()) {
warnln("Failed to open /sys/dev/block - {}", di.error());
VERIFY_NOT_REACHED();
}
while (di.has_next()) {
auto entry_name = di.next_path().split(':');
VERIFY(entry_name.size() == 2);
auto major_number = entry_name[0].to_uint<unsigned>().value();
auto minor_number = entry_name[1].to_uint<unsigned>().value();
switch (major_number) {
case 29: {
create_devtmpfs_block_device(String::formatted("/dev/fb{}", minor_number), 0666, 29, minor_number);
break;
}
case 30: {
create_devtmpfs_block_device(String::formatted("/dev/kcov{}", minor_number), 0666, 30, minor_number);
break;
}
case 3: {
create_devtmpfs_block_device(String::formatted("/dev/hd{}", offset_character_with_number('a', minor_number)), 0600, 3, minor_number);
break;
}
default:
warnln("Unknown block device {}:{}", major_number, minor_number);
break;
}
}
}
static void create_devtmpfs_char_device(String name, mode_t mode, unsigned major, unsigned minor) static void create_devtmpfs_char_device(String name, mode_t mode, unsigned major, unsigned minor)
{ {
if (auto rc = mknod(name.characters(), mode | S_IFCHR, makedev(major, minor)); rc < 0) if (auto rc = mknod(name.characters(), mode | S_IFCHR, makedev(major, minor)); rc < 0)
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
static void populate_devtmpfs_char_devices() static void populate_devtmpfs_char_devices_based_on_sysfs()
{ {
Core::DirIterator di("/sys/dev/char/", Core::DirIterator::SkipParentAndBaseDir); Core::DirIterator di("/sys/dev/char/", Core::DirIterator::SkipParentAndBaseDir);
if (di.has_error()) { if (di.has_error()) {
@ -183,7 +152,42 @@ static void populate_devtmpfs_char_devices()
auto major_number = entry_name[0].to_uint<unsigned>().value(); auto major_number = entry_name[0].to_uint<unsigned>().value();
auto minor_number = entry_name[1].to_uint<unsigned>().value(); auto minor_number = entry_name[1].to_uint<unsigned>().value();
switch (major_number) { switch (major_number) {
case 2: {
switch (minor_number) {
case 10: {
create_devtmpfs_char_device("/dev/devctl", 0660, 2, 10);
break;
}
default:
warnln("Unknown character device {}:{}", major_number, minor_number);
}
break;
}
default:
break;
}
}
}
static void populate_devtmpfs_devices_based_on_devctl()
{
auto f = Core::File::construct("/dev/devctl");
if (!f->open(Core::OpenMode::ReadOnly)) {
warnln("Failed to open /dev/devctl - {}", f->error_string());
VERIFY_NOT_REACHED();
}
DeviceEvent event;
while (f->read((u8*)&event, sizeof(DeviceEvent)) > 0) {
if (event.state != DeviceEvent::Inserted)
continue;
auto major_number = event.major_number;
auto minor_number = event.minor_number;
bool is_block_device = (event.is_block_device == 1);
switch (major_number) {
case 42: { case 42: {
if (!is_block_device) {
switch (minor_number) { switch (minor_number) {
case 42: { case 42: {
create_devtmpfs_char_device("/dev/audio", 0220, 42, 42); create_devtmpfs_char_device("/dev/audio", 0220, 42, 42);
@ -192,9 +196,15 @@ static void populate_devtmpfs_char_devices()
default: default:
warnln("Unknown character device {}:{}", major_number, minor_number); warnln("Unknown character device {}:{}", major_number, minor_number);
} }
}
break; break;
} }
case 29: { case 29: {
if (is_block_device) {
create_devtmpfs_block_device(String::formatted("/dev/fb{}", minor_number), 0666, 29, minor_number);
break;
}
switch (minor_number) { switch (minor_number) {
case 0: { case 0: {
create_devtmpfs_char_device("/dev/full", 0660, 29, 0); create_devtmpfs_char_device("/dev/full", 0660, 29, 0);
@ -206,10 +216,13 @@ static void populate_devtmpfs_char_devices()
break; break;
} }
case 229: { case 229: {
if (!is_block_device) {
create_devtmpfs_char_device(String::formatted("/dev/hvc0p{}", minor_number), 0666, major_number, minor_number); create_devtmpfs_char_device(String::formatted("/dev/hvc0p{}", minor_number), 0666, major_number, minor_number);
}
break; break;
} }
case 10: { case 10: {
if (!is_block_device) {
switch (minor_number) { switch (minor_number) {
case 0: { case 0: {
create_devtmpfs_char_device("/dev/mouse0", 0660, 10, 0); create_devtmpfs_char_device("/dev/mouse0", 0660, 10, 0);
@ -222,9 +235,11 @@ static void populate_devtmpfs_char_devices()
default: default:
warnln("Unknown character device {}:{}", major_number, minor_number); warnln("Unknown character device {}:{}", major_number, minor_number);
} }
}
break; break;
} }
case 85: { case 85: {
if (!is_block_device) {
switch (minor_number) { switch (minor_number) {
case 0: { case 0: {
create_devtmpfs_char_device("/dev/keyboard0", 0660, 85, 0); create_devtmpfs_char_device("/dev/keyboard0", 0660, 85, 0);
@ -233,9 +248,11 @@ static void populate_devtmpfs_char_devices()
default: default:
warnln("Unknown character device {}:{}", major_number, minor_number); warnln("Unknown character device {}:{}", major_number, minor_number);
} }
}
break; break;
} }
case 1: { case 1: {
if (!is_block_device) {
switch (minor_number) { switch (minor_number) {
case 5: { case 5: {
create_devtmpfs_char_device("/dev/zero", 0666, 1, 5); create_devtmpfs_char_device("/dev/zero", 0666, 1, 5);
@ -257,9 +274,23 @@ static void populate_devtmpfs_char_devices()
warnln("Unknown character device {}:{}", major_number, minor_number); warnln("Unknown character device {}:{}", major_number, minor_number);
break; break;
} }
}
break;
}
case 30: {
if (is_block_device) {
create_devtmpfs_block_device(String::formatted("/dev/kcov{}", minor_number), 0666, 30, minor_number);
}
break;
}
case 3: {
if (is_block_device) {
create_devtmpfs_block_device(String::formatted("/dev/hd{}", offset_character_with_number('a', minor_number)), 0600, 3, minor_number);
}
break; break;
} }
case 5: { case 5: {
if (!is_block_device) {
switch (minor_number) { switch (minor_number) {
case 1: { case 1: {
create_devtmpfs_char_device("/dev/console", 0666, 5, 1); create_devtmpfs_char_device("/dev/console", 0666, 5, 1);
@ -272,9 +303,11 @@ static void populate_devtmpfs_char_devices()
default: default:
warnln("Unknown character device {}:{}", major_number, minor_number); warnln("Unknown character device {}:{}", major_number, minor_number);
} }
}
break; break;
} }
case 4: { case 4: {
if (!is_block_device) {
switch (minor_number) { switch (minor_number) {
case 0: { case 0: {
create_devtmpfs_char_device("/dev/tty0", 0620, 4, 0); create_devtmpfs_char_device("/dev/tty0", 0620, 4, 0);
@ -311,10 +344,14 @@ static void populate_devtmpfs_char_devices()
default: default:
warnln("Unknown character device {}:{}", major_number, minor_number); warnln("Unknown character device {}:{}", major_number, minor_number);
} }
}
break; break;
} }
default: default:
if (!is_block_device)
warnln("Unknown character device {}:{}", major_number, minor_number); warnln("Unknown character device {}:{}", major_number, minor_number);
else
warnln("Unknown block device {}:{}", major_number, minor_number);
break; break;
} }
} }
@ -324,8 +361,8 @@ static void populate_devtmpfs()
{ {
mode_t old_mask = umask(0); mode_t old_mask = umask(0);
printf("Changing umask %#o\n", old_mask); printf("Changing umask %#o\n", old_mask);
populate_devtmpfs_char_devices(); populate_devtmpfs_char_devices_based_on_sysfs();
populate_devtmpfs_block_devices(); populate_devtmpfs_devices_based_on_devctl();
umask(old_mask); umask(old_mask);
} }