Linux block device IOCTL cmd codes - linux-device-driver

I am developing a Linux block driver and I am currently testing it. I have an IOCTL function which doesnt do anything at the moment. I just use a printk to print the cmd and arg parameters. When Linux starts up it calls the IOCTL function with a cmd of 5331 and arg of 0. I am trying to find out what this cmd could be. The only thing I can find is a reference to a CDROM capability. Does Linux think my device is a CDROM? If so how can I tell it otherwise? thanks
static int mydrv_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)

I found some example code for a ram block device. They implement an ioctl function and check for the 0x5331 code. They just return an error if the flag GENHD_FL_CD is not set.
case CDROM_GET_CAPABILITY: //0x5331 / * get capabilities * /
{
struct gendisk *disk = bdev->bd_disk;
if (bdev->bd_disk && (disk->flags & GENHD_FL_CD))
ret = SUCCESS;
else
ret = -EINVAL;
break;
}

Related

pcap_getnonblock() returns -3

I am quite new to using pcap lib, so please bear with me.
I am trying to use pcap_getnonblock function, the documentation says the following:
pcap_getnonblock() returns the current 'non-blocking' state of
the capture descriptor; it always returns 0 on 'savefiles' . If
there is an error, PCAP_ERROR is returned and errbuf is filled in
with an appropriate error message.
errbuf is assumed to be able to hold at least PCAP_ERRBUF_SIZE
chars.
I got -3 returned and the errbuf is an empty string, I couldn't understand the meaning of such result.
I believe this caused a socket error: 10065.
This problem happened only once and I could not reproduce it, but still it would be great to find its causing to prevent it in future executions.
Thanks in advance.
pcap_getnonblock() can return -3 - that's PCAP_ERROR_NOT_ACTIVATED. Unfortunately, that's not documented; I'll fix that.
Here's a minimal reproducible example that demonstrates this:
#include <pcap/pcap.h>
#include <stdio.h>
int
main(int argc, char **argv)
{
pcap_t *pcap;
char errbuf[PCAP_ERRBUF_SIZE];
if (argc != 2) {
fprintf(stderr, "Usage: this_program <interface_name>\n");
return 1;
}
pcap = pcap_create(argv[1], errbuf);
if (pcap == NULL) {
fprintf(stderr, "this_program: pcap_create(%s) failed: %s\n",
argv[1], errbuf);
return 2;
}
printf("pcap_getnonblock() returns %d on non-activated pcap_t\n",
pcap_getnonblock(pcap, errbuf));
return 0;
}
(yes, that's minimal, as 1) names of interfaces are OS-dependent, so it has to be a command-line argument and 2) if you don't run the program correctly, it should let you know what's happening, so you know what you have to do in order to reproduce the problem).
Perhaps pcap_getnonblock() and pcap_setnonblock() should be changed so that you can set non-blocking mode before activating the pcap_t, so that, when activated, it will be in non-blocking mode. It doesn't work that way currently, however.
I.e., you're allocating a pcap_t with pcap_create(), but you're not activating it with pcap_activate(). You need to do both in order to have a pcap_t on which you can capture.

Xcode C++ code in cocoa app about serial port get operation not permitted

I build a code in Xcode console with C++ project works perfectly before:
#include "SerialPort.hpp"
#include "TypeAbbreviations.hpp"
#include <iostream>
int main(int argc, const char * argv[]) {
//* Open port, and connect to a device
const char devicePathStr[] = "/dev/tty.usbserial-A104RXG4";
const int baudRate = 9600;
int sfd = openAndConfigureSerialPort(devicePathStr, baudRate);
if (sfd < 0) {
if (sfd == -1) {
printf("Unable to connect to serial port.\n");
}
else { //sfd == -2
printf("Error setting serial port attributes.\n");
}
return 0;
}
// * Read using readSerialData(char* bytes, size_t length)
// * Write using writeSerialData(const char* bytes, size_t length)
// * Remember to flush potentially buffered data when necessary
// * Close serial port when done
const char dataToWrite[]="abcd";
char databuffer[1024];
while(1){
readSerialData(databuffer, 4);
sleep(2);
writeSerialData(databuffer, 4);
sleep(2);
}
printf("end.\n");
return 0;
}
After this build, I tried to migrate it to my Xcode cocoa application with C++ wrappers below.
I am pretty sure my Wrapper works fine with test C++ code. That means, I can call C++ function from my ViewController.swift.
But there's one strange thing happened. I am not able to open connection with the following code:
sfd = open(portPath, (O_RDWR | O_NOCTTY | O_NDELAY));
if (sfd == -1) {
printf("Unable to open serial port: %s at baud rate: %d\n", portPath, baudRate);
printf("%s", std::strerror(errno));
return sfd;
}
There error message returns :
Unable to open serial port: /dev/tty.usbserial-A104RXG4 at baud rate: 9600
Operation not permitted
I've tried to change app sandbox configuration, set up my system preference to grant access to my app, also I disabled my rootless. (csrutil disable with command + R)
But the problem still persists:
&
I want to ask that:
1. Why my code on Xcode C++ project works fine but fail on swift's cocoa app on Xcode?
2. How to solve the "Operation not permitted" Issue.
My Xcode version is 11.3.1 and Mac OS is 10.14.6 Mojave.
I figure it out myself.
It's APP sandbox is bothering me.
All you need to do is turn off sandbox
Turn off it by click X on the mouse point.
If you want to add it back, just click +Capability and put it back on.
https://i.stack.imgur.com/ZOc18.jpg
reference : https://forums.developer.apple.com/thread/94177#285075

How to work out 'read/write' function using the libmodbus?(c code)

I'm gonna to read/write under the modbus-tcp specification.
So, I'm trying to code the client and server in the linux environment.
(I would communicate with the windows program(as a client) using the modbus-tcp.)
but it doesn't work as I want, so I ask you here.
I'm testing the client code for linux as a client and the easymodbus as a server.
I used the libmodbus code.
I'd like to read coil(0x01) and write coil(0x05).
When the code is executed using the libmodbus, 'ff' is printed out from the Unit ID part.(according to the manual, 01 should be output for modbus-tcp.
I don't know why 'ff' is printed(photo attached).
Wrong result:
Expected result:
'[00] [00] .... [00]' ; Do you know where to control this part?
Do you have or do you know the sample code that implements the 'read/write' function using the libmodbus?
please let me know the information, if you know that.
ctx = modbus_new_tcp("192.168.0.99", 502);
modbus_set_debug(ctx, TRUE);
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connection failed: %s\n",
modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
tab_rq_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));
memset(tab_rq_bits, 0, nb * sizeof(uint8_t));
tab_rp_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));
memset(tab_rp_bits, 0, nb * sizeof(uint8_t));
nb_loop = nb_fail = 0;
/* WRITE BIT */
rc = modbus_write_bit(ctx, addr, tab_rq_bits[0]);
if (rc != 1) {
printf("ERROR modbus_write_bit (%d)\n", rc);
printf("Address = %d, value = %d\n", addr, tab_rq_bits[0]);
nb_fail++;
} else {
rc = modbus_read_bits(ctx, addr, 1, tab_rp_bits);
if (rc != 1 || tab_rq_bits[0] != tab_rp_bits[0]) {
printf("ERROR modbus_read_bits single (%d)\n", rc);
printf("address = %d\n", addr);
nb_fail++;
}
}
printf("Test: ");
if (nb_fail)
printf("%d FAILS\n", nb_fail);
else
printf("SUCCESS\n");
free(tab_rq_bits);
free(tab_rp_bits);
/* Close the connection */
modbus_close(ctx);
modbus_free(ctx);
return 0;
That FF you see right before the Modbus function is actually correct. Quoting the Modbus Implementation Guide, page 23:
On TCP/IP, the MODBUS server is addressed using its IP address; therefore, the
MODBUS Unit Identifier is useless. The value 0xFF has to be used.
So libmodbus is just sticking to the Modbus specification. I'm assuming, then, that the problem is in easymodbus, which is apparently expecting you to use 0x01as the unit id in your queries.
I imagine you don't want to mess with easymodbus, so you can fix this problem pretty easily from libmodbus: just change the default unit id:
modbus_set_slave(ctx, 1);
You could also go with:
rc = modbus_set_slave(ctx, MODBUS_BROADCAST_ADDRESS);
ASSERT_TRUE(rc != -1, "Invalid broadcast address");
to make your client address all slaves within the network, if you have more than one.
You have more info and a short explanation of where this problem is coming from in the libmodbus man page for modbus_set_slave function.
For a very comprehensive example, you can check libmodbus unit tests
And regarding your question number 5, I don't know how to answer it, the zeros you mean are supposed to be the states (true or false) you want to write (or read) to the coils. For writing you can change them with the value field of function modbus_write_bit(ctx, address, value).
I'm very grateful for your reply.
I tested the read/write function using the 'unit-test-server/client' code you recommended.
I've reviewed the code, but there are still many things I don't know.
However, there is an address value that acts after testing each other with unit-test-server/client code and there is an address value that does not work
(Do you know why?).
-Checked and found that the UT_BITS_ADDRESS (address value) value operates from 0x130 to 0x150
-'error Illegal data address' occurs at values below -0x130 and above 0x150
-The address I want to read/write is 0x0001 to 0x0004(Do you know how to do?).
I want to know how to process and transmit data like the TX part of the right picture.
enter image description here
I'm running both client and server in my Linux environment and I'm doing read/write testing.
Among the wrong pictures...[06][FF]... <-- I want to know how to modify FF part (to change the value to 01 as shown in the picture)
enter image description here
and "modbus_set_slave" is the function for modbus rtu?
I'd like to communicate PC Program and Linux device in the end.
so Which part do I use that function?
I thanks for your concern again.

Page fault with newlib functions

I've been porting newlib to my very small kernel, and I'm stumped: whenever I include a function that references a system call, my program will page fault on execution. If I call a function that does not reference a system call, like rand(), nothing will go wrong.
Note: By include, I mean as long as the function, e.g. printf() or fopen(), is somewhere inside the program, even if it isn't called through main().
I've had this problem for quite some time now, and have no idea what could be causing this:
I've rebuilt newlib numerous times
Modified my ELF loader to load the
code from the section headers instead of program headers
Attempted to build newlib/libgloss separately (which failed)
Linked the libraries (libc, libnosys) through the ld script using GROUP, gcc and ld
I'm not quite sure what other information I should include with this, but I'd be happy to include what I can.
Edit: To verify, the page faults occurring are not at the addresses of the failing functions; they are elsewhere in the program. For example, when I call fopen(), located at 0x08048170, I will page fault at 0xA00A316C.
Edit 2:
Relevant code for loading ELF:
int krun(u8int *name) {
int fd = kopen(name);
Elf32_Ehdr *ehdr = kmalloc(sizeof(Elf32_Ehdr*));
read(fd, ehdr, sizeof(Elf32_Ehdr));
if (ehdr->e_ident[0] != 0x7F || ehdr->e_ident[1] != 'E' || ehdr->e_ident[2] != 'L' || ehdr->e_ident[3] != 'F') {
kfree(ehdr);
return -1;
}
int pheaders = ehdr->e_phnum;
int phoff = ehdr->e_phoff;
int phsize = ehdr->e_phentsize;
int sheaders = ehdr->e_shnum;
int shoff = ehdr->e_shoff;
int shsize = ehdr->e_shentsize;
for (int i = 0; i < pheaders; i++) {
lseek(fd, phoff + phsize * i, SEEK_SET);
Elf32_Phdr *phdr = kmalloc(sizeof(Elf32_Phdr*));
read(fd, phdr, sizeof(Elf32_Phdr));
u32int page = PMMAllocPage();
int flags = 0;
if (phdr->p_flags & PF_R) flags |= PAGE_PRESENT;
if (phdr->p_flags & PF_W) flags |= PAGE_WRITE;
int pages = (phdr->p_memsz / 0x1000) + 1;
while (pages >= 0) {
u32int mapaddr = (phdr->p_vaddr + (pages * 0x1000)) & 0xFFFFF000;
map(mapaddr, page, flags | PAGE_USER);
pages--;
}
lseek(fd, phdr->p_offset, SEEK_SET);
read(fd, (void *)phdr->p_vaddr, phdr->p_filesz);
kfree(phdr);
}
// Removed: code block that zeroes .bss: it's already zeroed whenever I check it anyways
// Removed: code block that creates thread and adds it to scheduler
kfree(ehdr);
return 0;
}
Edit 3: I've noticed that if I call a system call, such as write(), and then call printf() two or more times, I will get an unknown opcode interrupt. Odd.
Whoops! Figured it out: when I map the virtual address, I should allocate a new page each time, like so:
map(mapaddr, PMMAllocPage(), flags | PAGE_USER);
Now it works fine.
For those curious as to why it didn't work: when I wasn't including printf(), the size of the program was under 0x1000 bytes, so mapping with only one page was okay. When I include printf() or fopen(), the size of the program was much bigger so that's what caused the issue.

How to hide console window of subprocess?

I'm trying to write a very simple program to replace an existing executable. It should munge its arguments slightly and exec the original program with the new arguments. It's supposed to be invoked automatically and silently by a third-party library.
It runs fine, but it pops up a console window to show the output of the invoked program. I need that console window to not be there. I do not care about the program's output.
My original attempt was set up as a console application, so I thought I could fix this by writing a new Windows GUI app that did the same thing. But it still pops up the console. I assume that the original command is marked as a console application, and so Windows automatically gives it a console window to run in. I also tried replacing my original call to _exec() with a call to system(), just in case. No help.
Does anyone know how I can make this console window go away?
Here's my code:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
char* lpCmdLine,
int nCmdShow)
{
char *argString, *executable;
// argString and executable are retrieved here
std::vector< std::string > newArgs;
// newArgs gets set up with the intended arguments here
char const ** newArgsP = new char const*[newArgs.size() + 1];
for (unsigned int i = 0; i < newArgs.size(); ++i)
{
newArgsP[i] = newArgs[i].c_str();
}
newArgsP[newArgs.size()] = NULL;
int rv = _execv(executable, newArgsP);
if (rv)
{
return -1;
}
}
Use the CreateProcess function instead of execve. For the dwCreationFlags paramter pass the CREATE_NO_WINDOW flag. You will also need to pass the command line as a string as well.
e.g.
STARTUPINFO startInfo = {0};
PROCESS_INFORMATION procInfo;
TCHAR cmdline[] = _T("\"path\\to\\app.exe\" \"arg1\" \"arg2\"");
startInfo.cb = sizeof(startInfo);
if(CreateProcess(_T("path\\to\\app.exe"), cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startInfo, &procInfo))
{
CloseHandle(procInfo.hProcess);
CloseHandle(procInfo.hThread);
}
Aha, I think I found the answer on MSDN, at least if I'm prepared to use .NET. (I don't think I'm really supposed to, but I'll ignore that for now.)
System::String^ command = gcnew System::String(executable);
System::Diagnostics::Process^ myProcess = gcnew Process;
myProcess->StartInfor->FileName = command;
myProcess->StartInfo->UseShellExecute = false; //1
myProcess->StartInfo->CreateNowindow = true; //2
myProcess->Start();
It's those two lines marked //1 and //2 that are important. Both need to be present.
I really don't understand what's going on here, but it seems to work.
You need to create a non-console application (i.e. a Windows GUI app). If all this app does is some processing of files or whatever, you won't need to have a WinMain, register any windows or have a message loop - just write your code as for a console app. Of course, you won't be able to use printf et al. And when you come to execute it, use the exec() family of functions, not system().