How to calculate size of MMIO-mapped region from BAR address in PCIe - io

I've been diving deeper into how PCIe works in general, and I'm stuck at where many books and websites talk about PCIe configuration space.
What I have learned so far is that for each of the assigned device with its BDF (bus-device-function bits), there corresponds a 4KB configuration space for that device, which includes the 64B region as below:
I understand up to the point where each of the base address registers (that represent memory-mapped region) are decoded as below:
(both of the images are from this site)
What I don't get is how the size of the region is determined. For example, in one server, I get the following for a GPU connected to BDF 00:05.0 command lspci -x -v -s 05:00.0:
05:00.0 VGA compatible controller: NVIDIA Corporation GV100 [TITAN V] (rev a1) (prog-if 00 [VGA controller])
Subsystem: NVIDIA Corporation GV100 [TITAN V]
Flags: bus master, fast devsel, latency 0, IRQ 80, NUMA node 0
Memory at f8000000 (32-bit, non-prefetchable) [size=16M]
Memory at a0000000 (64-bit, prefetchable) [size=256M]
Memory at b0000000 (64-bit, prefetchable) [size=32M]
I/O ports at d000 [size=128]
[virtual] Expansion ROM at 000c0000 [disabled] [size=128K]
Capabilities: <access denied>
Kernel driver in use: nvidia
Kernel modules: nvidiafb, nouveau, nvidia_drm, nvidia
00: de 10 81 1d 07 05 10 00 a1 00 00 03 00 00 80 00
10: 00 00 00 f8 0c 00 00 a0 00 00 00 00 0c 00 00 b0
20: 00 00 00 00 01 d0 00 00 00 00 00 00 de 10 18 12
30: 00 00 00 00 60 00 00 00 00 00 00 00 0b 01 00 00
We can see that the value of BAR0 is 0xf8000000. But how do we know the size of the region that starts at address 0xf8000000? From some sites I've checked (one, two, and three) they talk about:
(1) finding the complement value of the address which should be the length of the region (which does not make sense to me in a few ways) or
(2) since 0xf8000000 is 1111 1000 0000 0000 0000 0000 0000 0000, the size of the region is 2^27=128MB because there are 27 consecutive 0s until it meets the first 1.
But both of these methods are wrong, because the lspci command said that particular region has 16MB mapped, not 128MB.
So here are my real questions:
1. How exactly should the memory region size be calculated?
2. Also, the memory mapped above seems to add up to 16M+256M+32M+128(+128K), but the actual size of the GPU memory is a little over 12GB. Is it right that not all of the GPU memory is mapped with MMIO via PCIe?
Thanks in advance.

The OSDev link you mentioned defines the protocol for probing the BAR:
To determine the amount of address space needed by a PCI device, you
must save the original value of the BAR, write a value of all 1's to
the register, then read it back. The amount of memory can then be
determined by masking the information bits, performing a bitwise NOT
('~' in C), and incrementing the value by 1. The original value of the
BAR should then be restored. The BAR register is naturally aligned and
as such you can only modify the bits that are set.

Related

From which factors depends the le scan rate of bluez and how can it be improved?

I want to write a script, that opens a connection to a Bluetooth Low Energy device as soon as it reaches a certain RSSI threshold. First I wrote a script in Python using bluepy but was disappointed by the responsiveness. So I thought it is probably a problem with the library, so I re-wrote it in NodeJS, but the result was the same. So I dug deeper...
The script was tested on my Macbook Pro and a Raspberry Pi 4. On the Macbook the ble devices appeared slightly faster than on the Raspi, but not much.
I found out, that on Linux all Bluetooth communication runs over bluez, which can be controlled for example by hcitool and bluetoothctl. So I used them to see how fast the updates of the RSSI are coming in there. And already there the responsiveness is not fast enough. So it seem like Linux is not processing the advertisement packages from the ble devices fast enough.
The devices are advertising every 100ms (also tried 50ms, no difference), but I see only one RSSI update every approx. 1 second. AND: It feels like the packages are coming in bursts. So like a couple of them in 4 seconds, then nothing for one second and then another burst for 4 seconds.
So my question is: From which factors does the data rate depend, how fast the data is coming in? And how can I improve the data rate?
Are there maybe better ble chips, I could use, or any settings I could play around with?
By the way: For making sure, that there are no problems with lost packets, the ble devices are always very close to the Macbook/Raspi.
Here is an example for using bluetoothctl:
# sudo bluetoothctl
# agent on
# scan on
BlueZ command line tools are not designed to give you real-time output of scanned packets. You are better off using the BlueZ C APIs. Here is a simple command line program I wrote in C that will give you the raw output of every BLE advertising packet that BlueZ detects. For advertisers going at 10 Hz, I typically see 8-9 packets per second (you don't ever receive 100%).
https://github.com/davidgyoung/ble-scanner
I put instructions at the top of the file for compiling the C code. Once you do so, you can just use it like this:
$ ./scanner
B8:27:EB:1F:93:4D -68 02 01 06 11 06 82 75 25 D9 37 9D D7 8F 5F 4A F4 20 00 00 75 30
71:5C:23:9D:BC:7F -68 02 01 1A 02 0A 0C 0B FF 4C 00 10 06 03 1A 3B D4 B2 EB
B8:27:EB:1F:93:4D -68 02 01 06 11 06 82 75 25 D9 37 9D D7 8F 5F 4A F4 20 00 00 75 30
The output starts with the MAC, then the RSSI, then the hex bytes of the advertisement.

Interpret AVRCP packets

After some mucking about, I have got a pybluez script to connect to an AVRCP profile on various devices, and read the responses.
Code snippet:
addr="e2:8b:8e:89:6c:07" #S530 white
port=23
if (port>0):
print("Attempting to connect to L2CAP port ",port)
socket=bluetooth.BluetoothSocket(bluetooth.L2CAP);
socket.connect((addr,port))
print("Connected.")
while True:
print("Waiting on read:")
data=socket.recv(1024)
for b in data:
print("%02x"%b,end=" ")
print()
socket.close()
The results I'm getting when I press the button on the earpiece are as follows:
Attempting to connect to L2CAP port 23
Connected.
Waiting on read:
10 11 0e 01 48 00 00 19 58 10 00 00 01 03
Waiting on read:
20 11 0e 00 48 7c 44 00
Waiting on read:
30 11 0e 00 48 7c 46 00
Waiting on read:
40 11 0e 00 48 7c 44 00
After careful reading of the spec, it looks like I'm seeing PASSTHROUGH commands, with 44 being the "PLAY" operation command, and 46 being "PAUSE" (I think)
I don't know what the 10 11 0e means, apart from the fact that the first byte appears to be some sort of sequence number.
My issue is threefold:
I don't know where to find a list of valid operation_ids. It's
mentioned in the spec but not defined apart from a few random
examples.
The spec makes reference to subunit type and Id, (which would be the
48 in the above example) again without defining them AFAICT.
There is no mention of what the leading three bytes are. They may
even be part of L2CAP and nothing directly to do with AVRCP, I'm not
familiar enough with pybluez to tell.
Any assistance in any of the above points would be helpful.
Edit: For reference, the details of the AVRCP spect appears to be here: https://www.bluetooth.org/docman/handlers/DownloadDoc.ashx?doc_id=119996
The real answer is that the specification document assumes you have read other specification documents.
The three header bytes are part of the AVCTP transport layer:
http://www.cs.bilkent.edu.tr/~korpe/lab/resources/AVCTP%20Spec%20v1_0.pdf
In short:
0: 7..4: Incrementing transaction id. 0x01 to 0x0f
3..2: Packet type 00 = self contained packet
1 : 0=request 1=response
0 : 0=PID recognized 1: PID error
1-2: 2 byte bigendian profile id (in this case 110e, AVRCP)
The rest is described in the AVRCP profile doc, https://www.bluetooth.org/docman/handlers/DownloadDoc.ashx?doc_id=119996
I don't find the documentation to be amazingly clear.
I have provided a sample application which seems to work for most of the AVRCP devices I have been able to test:
https://github.com/rjmatthews62/BtAVRCP

APDU command change IMSI SIM CARD

I am trying to use UPDATE BINARY command using APDU command for modify IMSI code, but The response is 98 04.
A0 A4 00 00 02 3F 00 -> SELECT MF
A0 A4 00 00 02 7F 20 -> Select DF_GSM
A0 A4 00 00 02 6F 07 ->Select EF_IMSI
A0 D6 00 00 09 [08 79 03 30 60 00 61 33 23] -> UPDATE IMSI FOR RANDOM NUMBER
when doing this I get the following response 98 04 and it is not modified.
According to the documentation The response 98 04 can mean the following:
access condition not fulfilled
unsuccessful CHV verification, at least one attempt left
unsuccessful UNBLOCK CHV verification, at least one attempt left
authentication failed
How I can change IMSI?
Thank you.
From 3GPP-TS-11.011 - You have to verify ADM first in order to update EF_IMSI. See link. Typically only the network has the "password". Otherwise anyone with the password can impersonate the identity of someone else's SIM card.
EF_IMSI Update Conditions
In order to update IMSI file on SIM , UPDATE command header and data part should be generated according GSM 03.48 specification. For the SIM file structure 31.102 is the specification.
Command header parameters should be obtained from SIM vendor. Minimum security Level parameter will definitely enforce encryption and cryptographic cHecksum usage for securing the command data, because real SIM card card manager expects MSL parameters something like that 0x25, so KiC and KiD key values are required.
You need first to Verify CHV (PIN1 for IMSI).
Use the following APDU and replace your PIN1 value.
-> A0 20 00 01 08 31 32 33 34 FF FF FF FF
<- 90 00
Caution: If you use wrong PIN value, it will be disabled after 3 times.

Ford CAN Data and ELM327

I am trying to use a Bluetooth ELM327 wireless OBD-II receiver to obtain data from a vehicles OBD-II port. I am not trying to gather information about the engine, but rather some of the electronics in the vehicle. I have been given certain commands to access the devices and have been successful using different devices and software other than the ELM327.
I do not have much experience dealing with the CAN bus and data transfer in general; so forgive me if I am leaving out crucial pieces of this process. However, I do understand CAN basics such as message headers and data bytes.
So far I have been using the Ford DET tool to gather data from the device. I am able to send an 8 byte CAN message and receive data back. I have many commands which I need to parse proper data from the output they produce. For example, if I were to send the command
0x727 03 19 02 8F
My log file shows:
00184.3548 (Rx) 0x72F 10 0F 59 02 CA E1 00 00
00024.8556 (Rx) 0x72F 10 0F 59 02 CA E1 00 00 --- Request DTC Info: Report DTCs By Status Mask (StatusMask: 8F)
00189.4469 (Tx) 0x727 03 19 02 8F 00 00 00 00 --- Request DTC Info: Report DTCs By Status Mask (StatusMask: 8F)
00189.4549 (Rx) 0x72F 10 0F 59 02 CA E1 00 00
00189.4572 (Tx) 0x727 30 00 00 00 00 00 00 00
00189.4591 (Rx) 0x72F 21 0A E1 01 00 0A 9A 89
00189.4612 (Rx) 0x72F 22 13 0A 00 00 00 00 00 --- Pos Resp to Read DTCs By Status Mask (3 DTCs)
Here is what happens when talking to the ELM327 with goSerial. I have included all the commands to illustrate how I am using the ELM327 device.
>ath1
OK
>ats1
OK
>atal
OK
>at sh 727 <-- set the message header to 0x727
OK
>03 19 02 8f
72F 03 7F 03 11
>
As you can see, the result output on the final line is much shorter than that the Diagnostic Engineering tool is giving me. Am I not configuring the device properly?
Basically I am trying to have the ELM327 output match the output from the Ford DET tool. I understand that this is a very vague question.
Here is some other information about my configuration:
Baud rate: 38400 (standard for vehicles?)
CAN version: ISO 15765-4
All my commands start with 0x727. Flow control is transmitted with 0x727 and 0x7A7.
Also, I have already read over most of the ELM327 documentation so please do not leave that as a solution.
What makes you think that "the result output on the final line is much shorter than that the
Diagnostic Engineering tool is giving me" ?
Actually, the response of the ECU is perfectly valid:
72F 03 7F 03 11
72F - ID of the CAN message
03 - Length of data bytes
7F - Negative response
03 - The negative response is for command 03
11 - Not supported
You have an error in the line where you are sending the CAN message "03 19 02 8f".
You should send the message like this: "19 02 8f".

/dev/input keyboard format

I've been playing around with capturing the input from my keyboard device:
/dev/input/by-path/platform-i8042-serio-0-event-kbd
for me, and I was wondering if there was any specification for what it returns, using
od -tx1 /dev/input/by-path/platform-i8042-serio-0-event-kbd
to listen. I'm curious mostly due to the behavior of certain keys; the meta, arrow keys, numpad forward slash.
0520300 ac 9d 86 4c 6b 0f 04 00 04 00 04 00 (db) 00 00 00
0520320 ac 9d 86 4c 8c 0f 04 00 01 00 (7d) 00 00 00 00 00
0520340 ac 9d 86 4c 95 0f 04 00 00 00 00 00 00 00 00 00
Every other key I've looked at so far has the two bytes in parentheses as matching values, is there any reason these are special?
/dev/input/by-path/platform-i8042-serio-0-event-kbd is just a symlink to /dev/input/eventX event device file. Data can be read from event device files as
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
defined in /usr/include/linux/input.h.
Possible values of type are prefixed with EV_.
Possible values of code depend on type. They are prefixed with KEY_ or BTN_ or REL_ or so on.
Possible values of value depend on both type and code. For example for key-press events value equals 1 and for key-release events 0.
You can examine event data with:
evtest /dev/input/eventX
where X is the event device number of your keyboard (or any other event device). One key press or release normally emits three events (EV_MSC, EV_KEY and EV_SYN).
Some keys have unusual scan codes...
From: http://www.beyondlogic.org/keyboard/keybrd.htm (with edits) :
Now there's 101 keys and 8 bits make 256 different combinations, thus you only need to send one byte per key, right?
Nope. Unfortunately, a handful of the keys found on your keyboard are extended keys, and thus require two scan codes. These keys are preceded by a E0 (hex). But it doesn't stop at two scan codes either. How about E1,14,77,E1,F0,14,F0,77! Now that can't be a valid scan code? Wrong again. It's happens to be sent when you press the Pause/Break key. Don't ask me why they have to make it so long! Maybe they were having a bad day or something?

Resources