I'm writing a simple program to set and clear a pin (the purpose is to use that pin as a custom spi_CS).
I'm able to export that pin (gpio1_17, port 9 pin 23 bb white) and to use that trough the filesystem but I have to drive it faster.
This is the code:
uint32_t *gpio;
int fd = open("/dev/mem", O_RDWR|O_SYNC);
if (fd < 0){
fprintf(stderr, "Unable to open port\n\r");
exit(fd);
}
gpio =(uint32_t *) mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO1_offset); // start of GPIOA
if(gpio == (void *) -1) {
printf("Memory map failed.\n");
exit(0);
} else {
printf("Memory mapped at address %p.\n", gpio);
}
printf("\nGPIO_OE:%X\n",gpio[GPIO_OE/4]);
gpio[GPIO_OE/4]=USR1;
printf("\nGPIO_OE:%X\n",gpio[GPIO_OE/4]);
printf("\nGPIO_CLEARDATAOUT:%X\n",gpio[GPIO_CLEARDATAOUT/4]);
gpio[GPIO_CLEARDATAOUT/4]=USR1;
printf("\nGPIO_CLEARDATAOUT:%X\n",gpio[GPIO_CLEARDATAOUT/4]);
sleep(1);
printf("\nGPIO_SETDATAOUT%X\n",gpio[GPIO_SETDATAOUT/4]);
gpio[GPIO_DATAOUT/4]=USR1;
printf("\nGPIO_SETDATAOUT%X\n",gpio[GPIO_SETDATAOUT/4]);
with
#define GPIO1_offset 0x4804c000
#define GPIO1_size 0x4804cfff-GPIO1_offset
#define GPIO_OE 0x134
#define GPIO_SETDATAOUT 0x194
#define GPIO_CLEARDATAOUT 0x190
#define GPIO_DATAOUT 0x13C
#define USR1 1<<17
I'm able to outputenable that pin, beacuse if I put it high before running the program, that ping goes low. But I cannot set and reset it. Any ideas?
Why are you directly modifying the registers? It is way easier to just use it as a linux GPIO:
#define GPIO_1_17 "49"
int gpio;
status_codes stat = STATUS_SUCCESS;
//Export our GPIOs for use
if((gpio = open("/sys/class/gpio/export", O_WRONLY)) >= 0) {
write(gpio, GPIO_1_17, strlen(GPIO_1_17));
close(gpio);
} else {
stat = STATUS_GPIO_ACCESS_FAILURE;
break;
}
//Set the direction and pull low
if((gpio = open("/sys/class/gpio/gpio" GPIO_1_17 "/direction", O_WRONLY)) >= 0) {
write(gpio, "out", 3); // Set out direction
close(gpio);
} else {
stat = STATUS_GPIO_ACCESS_FAILURE;
break;
}
if((gpio = open("/sys/class/gpio/gpio" GPIO_1_17 "/value", O_WRONLY)) >= 0) {
write(gpio, "0", 1); // Pull low
close(gpio);
} else {
stat = STATUS_GPIO_ACCESS_FAILURE;
break;
}
Then just make sure it is muxed as a gpio in your inits.
As far as the mmap method you have above you addressing looks correct. The addresses in the ref manual are byte addresses and you are using a 32-bit pointer so what you have there is correct. However, this line: gpio[GPIO_OE/4]=USR1 makes every pin on GPIO1 an output except for 17 which it makes an input (0 = output and 1 = input). You probably meant this: gpio[GPIO_OE/4] &= ~USR1
Also i believe you meant to have gpio[GPIO_SETDATAOUT/4]=USR1; instead of gpio[GPIO_DATAOUT/4]=USR1; They will both cause GPIO1_17 to be set; however, using what you have will also set all the other pins on GPIO1 to be 0.
I would definitely recommend using the designed kernel interfaces because mmap'ing stuff that is also controlled by the kernel can be asking for trouble.
Good Luck! : )
EDIT: My bad just realized you said why you were not driving it directly through the file system because you needed to drive it faster! You may also want to consider writing/modifying the SPI driver so that the stuff is being done in Kernel land if speed is what your after. The omap gpio interfaces are simple to use there as well, just request and set : ).
Related
I have a FTDI USB3 development board and some FTDI provided code for accessing it. The code works fine for things like the Device number, VID/PID etc. but always returns zero for the 'ftHandle'. As the handle is required for driving the board, this is not helpful! Can anyone see why this should happen?
static FT_STATUS displayDevicesMethod2(void)
{
FT_STATUS ftStatus;
FT_HANDLE ftHandle = NULL;
// Get and display the list of devices connected
// First call FT_CreateDeviceInfoList to get the number of connected devices.
// Then either call FT_GetDeviceInfoList or FT_GetDeviceInfoDetail to display device
info.
// Device info: Flags (usb speed), device type (600 e.g.), device ID (vendor,
product),
handle for subsequent data access.
DWORD numDevs = 0;
ftStatus = FT_CreateDeviceInfoList(&numDevs); // Build a list and return number
connected.
if (FT_FAILED(ftStatus))
{
printf("Failed to create a device list, status = %d\n", ftStatus);
}
printf("Successfully created a device list.\n\tNumber of connected devices: %d\n",
numDevs);
// Method 2: using FT_GetDeviceInfoDetail
if (!FT_FAILED(ftStatus) && numDevs > 0)
{
ftHandle = NULL;
DWORD Flags = 0;
DWORD Type = 0;
DWORD ID = 0;
char SerialNumber[16] = { 0 };
char Description[32] = { 0 };
for(DWORD i = 0; i <numDevs; i++)
{
ftStatus = FT_GetDeviceInfoDetail(i, &Flags, &Type, &ID, NULL, SerialNumber,
Description, &ftHandle);
if (!FT_FAILED(ftStatus))
{
printf("Device[%d] (using FT_GetDeviceInfoDetail)\n", i);
printf("\tFlags: 0x%x %s | Type: %d | ID: 0x%08X | ftHandle=0x%p\n",
Flags,
Flags & FT_FLAGS_SUPERSPEED? "[USB 3]":
Flags & FT_FLAGS_HISPEED? "[USB 2]":
Flags & FT_FLAGS_OPENED? "[OPENED]": "",
Type,
ID,
ftHandle);
printf("\tSerialNumber=%s\n", SerialNumber);
printf("\tDescription=%s\n", Description);
}
}
}
return ftStatus;
}
This is indeed not super straight forward, but a short peek in the FTDI Knowledgebase yields:
This function builds a device information list and returns the number of D2XX devices connected to the system. The list contains information about both unopen and open devices.
A handle only exists for an opened device. Thus, I assume that your code does not already include that step. If so you need to open it first, e.g. using FT_Open. There are plenty of examples available. You can check their page or stackoverflow for a working example.
I guess the question is pretty straight forward itself.
Is there any way of detecting the memory (or getting he memory map) and framebuffer (or Graphics Output Protocol) after using ExitBootServices in UEFI in 64-bit mode? If so then how and is there any documentation?
I know that after using ExitBootServices, you the the sole owner of the entire machine.
There are many ways of getting the memory map but they all take help of the bootloader. I want to get the memory map directly from the kernel. Many websites such as OSDev and github sources use bootloaders to get the memory map and framebuffer.
After using ExitBootServices, I'm left in 64-bit mode and the only page on OSDev wiki about getting the memory map works on 32-bit architecture.
I have no language preferences, it may be in C, assembly or whatever and please don't say that it's useless or complicated or difficult to do. I just want an answer.
First, (Probably in (U)EFI) U cannot call boot services which is the only way to get what you want, you can get the memory map & Frame Buffer before ExitBootServices() and pass them to the kernel, you're lucky cause I'm not always on this platform, I've a Hybrid Boot Mechanism with LEGACY BIOS & UEFI Support, and here is an example of how to do that (I'm working on EDK2 Which is the Official Implementation of EFI)
This is how you get the frame buffer from G.O.P ( UGA documentation is removed ):
FRAME_BUFFER_DESCRIPTOR* GraphicsOutputProtocolInitialize(){
// First, we need to query the firmware of all G.O.P Protocol Instances
// (Each instance may represent a GPU or a monitor, GOP features multiple-screens
// U have asked for a simple implementation so we will use only 1 frame buffer
EFI_STATUS status = 0;
EFI_HANDLE* HandleBuffer = NULL;
UINTN NumProtocolHandles = 0;
if(EFI_ERROR(gBS->LocateHandleBuffer(
ByProtocol, &gEfiGraphicsOutputProtocolGuid, NULL,
&NumProtocolHandles, &HandleBuffer
)) || !NumProtocolHandles) return NULL;
// Then u need to create a structure that you can pass to the kernel containing information about frame buffers
FRAME_BUFFER_DESCRIPTOR* FrameBuffer = NULL;
if(EFI_ERROR(gBS->AllocatePool(
EfiLoaderData, sizeof(FRAME_BUFFER_DESCRIPTOR), (void**)&FrameBuffer
))) ALLOCATION_PROBLEM;
ZeroMemory((void*)FrameBuffer, sizeof(FRAME_BUFFER_DESCRIPTOR));
EFI_GRAPHICS_OUTPUT_PROTOCOL* gop = NULL;
status = gBS->OpenProtocol(
HandleBuffer[0], // Get first Graphics Output Protocol Instance
&gEfiGraphicsOutputProtocolGuid,
(void**)&gop,
NULL,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if(EFI_ERROR(status) || !gop)
{
return NULL;
}
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* ginfo = NULL;
UINTN info_size = 0;
// if mode is not yet set by firmware, then set first mode
if(status == EFI_NOT_STARTED || !gop->Mode){
status = gop->SetMode(gop, 0);
if(EFI_ERROR(status) || !gop->Mode->Mode)
{
return NULL;
}
}
// Now we will ask firmware for the current Video Mode
status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &ginfo);
if(status != EFI_SUCCESS || !ginfo){
return NULL;
}
// You can also list availaible video modes
for(UINTN i = 0;i<gop->Mode->MaxMode;i++) {
status = gop->QueryMode(gop, i, &info_size, &ginfo);
if(status != EFI_SUCCESS || !ginfo){
return NULL;
}
// To set the mode :
status = gop->SetMode(gop, i);
if(EFI_ERROR(status))
{
return NULL;
}
}
FrameBuffer->FrameBufferSize = gop->Mode->FrameBufferSize;
FrameBuffer->HorizontalResolution = gop->Mode->Info->HorizontalResolution;
FrameBuffer->VerticalResolution = gop->Mode->Info->VerticalResolution;
FrameBuffer->FrameBufferBase = (char*)gop->Mode->FrameBufferBase;
ZeroMemory((void*)FrameBuffer, sizeof(FRAME_BUFFER_DESCRIPTOR));
}
return FrameBuffer;
}
This is how you get the memory map :
On the first Call you will get the size of the memory map (Status must be EFI_BUFFER_TOO_SMALL)
Then you add 2 * descriptor size coz there is always 2 additional entries, then you allocate buffer for memory map
On the second call, you will get the actual memory map (Status must be EFI_SUCCESS)
Then u can list memory map entries normally
This is how u make a call to GetMemoryMap() :
EFI_MEMORY_DESCRIPTOR* memory_map = NULL;
UINTN map_size = 0, map_key = 0, descriptor_size = 0;
// Must return EFI_BUFFER_TOO_SMALL on First Call
// map_size will contain buffer size needed
EFI_STATUS s = SystemTable->BootServices->GetMemoryMap(&map_size,memory_map,&map_key,&descriptor_size,&descriptor_version);
map_size+=2*descriptor_size; // this padding must be added since there is 2 additionnal entries
However, u can always ask for a code sample, the previous code of (G.O.P) is just copy-pasted and modified to make it a little bit easier to understand, it is not compiled so it may contain some faults.
When I try to hook MGCopyAnswer, I get a crash. I'm trying this on a jailbroken iPhone 5s in iOS 8.3, arm64 binaries.
#import <substrate.h>
extern "C" CFTypeRef MGCopyAnswer(CFStringRef);
MSHook(CFTypeRef, MGCopyAnswer, CFStringRef key)
{
return _MGCopyAnswer(key);
}
%ctor
{
NSString *appID = [[NSBundle mainBundle] bundleIdentifier];
if ( appID && [appID isEqualToString:#"com.test.test"]) {
MSHookFunction(MGCopyAnswer, MSHake(MGCopyAnswer));
}
}
Makefile:
ARCHS = armv7 armv7s arm64
TARGET = iphone:latest:8.0
test2_FRAMEWORKS = UIKit
include theos/makefiles/common.mk
TWEAK_NAME = test2
test2_FILES = Tweak.xm
test2_LIBRARIES = MobileGestalt
include $(THEOS_MAKE_PATH)/tweak.mk
after-install::
install.exec "killall -9 SpringBoard"
Crash log:
Version: 1.44 (1.4)
Code Type: ARM-64 (Native)
Parent Process: launchd [1]
Date/Time: 2016-04-25 01:09:31.810 +0800
Launch Time: 2016-04-25 01:09:31.564 +0800
OS Version: iOS 8.3 (12F70)
Report Version: 105
Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x000000000068fe68
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libMobileGestalt.dylib 0x0000000195af7e84 0x195af4000 + 16004
1 libMobileGestalt.dylib 0x0000000195af82bc MGGetBoolAnswer + 32
2 AppSupport 0x000000018b020594 __CPIsInternalDevice_block_invoke + 16
3 libdispatch.dylib 0x0000000196c99950 _dispatch_client_callout + 12
4 libdispatch.dylib 0x0000000196c9a828 dispatch_once_f + 92
5 AppSupport 0x000000018b02057c CPIsInternalDevice + 60
6 UIKit 0x0000000189b58750 ___UIApplicationUsesAlternateUI_block_invoke + 12
7 libdispatch.dylib 0x0000000196c99950 _dispatch_client_callout + 12
8 libdispatch.dylib 0x0000000196c9a828 dispatch_once_f + 92
9 UIKit 0x0000000189923750 UIApplicationInitialize + 1872
10 UIKit 0x0000000189922b1c UIApplicationMain + 320
MGCopyAnswer:
-> 0x193a7fe84 <+0>: .long 0x002d7c28 ; unknown opcode
0x193a7fe88 <+4>: .long 0x00000001 ; unknown opcode
0x193a7fe8c <+8>: stp x20, x19, [sp, #32]
0x193a7fe90 <+12>: stp x29, x30, [sp, #48]
0x193a7fe94 <+16>: add x29, sp, #48
0x193a7fe98 <+20>: sub sp, sp, #48
0x193a7fe9c <+24>: mov x19, x1
0x193a7fea0 <+28>: mov x22, x0
0x193a7fea4 <+32>: movz w0, #0
0x193a7fea8 <+36>: bl 0x193a7f564 ; ___lldb_unnamed_function54$$libMobileGestalt.dylib
0x193a7feac <+40>: orr w1, wzr, #0x1
0x193a7feb0 <+44>: mov x0, x22
0x193a7feb4 <+48>: bl 0x193a7f5fc ; ___lldb_unnamed_function56$$libMobileGestalt.dylib
0x193a7feb8 <+52>: mov x21, x0
0x193a7febc <+56>: movz w20, #0
0x193a7fec0 <+60>: cbz x21, 0x193a7fefc ; <+120>
0x193a7fec4 <+64>: ldr w20, [x21, #148]
0x193a7fec8 <+68>: mov x0, x21
orig_MGCopyAnswer
0x104234000: movz x1, #0
0x104234004: stp x24, x23, [sp, #-64]!
0x104234008: stp x22, x21, [sp, #16]
0x10423400c: ldr x16, #8
0x104234010: br x16
0x104234014: .long 0x93a7fe8c
0x104234018: .long 0x00000001 ; unknown opcode
What am I doing wrong?
You cannot hook MGCopyAnswer directly because it is too short.
When CydiaSubstrate hooks a C function, it sorts of overwrites an assembly version of goto your_function; at the beginning of the original function. This "goto" in ARM64 is 16 bytes in size, which means if the original function is too short (< 16 bytes), CydiaSubstrate can spill over and corrupt the neighboring functions.
This is exactly why the problem of MGCopyAnswer. The implementation of MGCopyAnswer is basically (on 9.3.2 arm64):
01 00 80 d2 movz x1, #0
01 00 00 14 b MGCopyAnswer_internal
which is just 8 bytes (< 16 bytes) in size. So CydiaSubstrate will corrupt the 8 bytes after the end of MGCopyAnswer.
Unfortunately, MGCopyAnswer_internal is right after MGCopyAnswer, and even worse this function and is called by MGGetBoolAnswer as well. Since MGCopyAnswer_internal is corrupt, you get an EXC_BAD_INSTRUCTION crash inside libMobileGestalt.
A good news for MGCopyAnswer is that, you could just hook MGCopyAnswer_internal! This has an additional benefit that many related functions like MGGetBoolAnswer, MGCopyAnswerWithError, MGCopyMultipleAnswers etc. can respond to your change as well. The bad thing is that MGCopyAnswer_internal is completely internal, and there is no symbols pointing to it. We could rely on the fact that MGCopyAnswer_internal is exactly 8 bytes after MGCopyAnswer on ARM64, and develop this ugly hack:
static CFPropertyListRef (*orig_MGCopyAnswer_internal)(CFStringRef prop, uint32_t* outTypeCode);
CFPropertyListRef new_MGCopyAnswer_internal(CFStringRef prop, uint32_t* outTypeCode) {
return orig_MGCopyAnswer_internal(prop, outTypeCode);
}
extern "C" MGCopyAnswer(CFStringRef prop);
static CFPropertyListRef (*orig_MGCopyAnswer)(CFStringRef prop);
CFPropertyListRef new_MGCopyAnswer(CFStringRef prop) {
return orig_MGCopyAnswer(prop);
}
%ctor {
uint8_t MGCopyAnswer_arm64_impl[8] = {0x01, 0x00, 0x80, 0xd2, 0x01, 0x00, 0x00, 0x14};
const uint8_t* MGCopyAnswer_ptr = (const uint8_t*) MGCopyAnswer;
if (memcmp(MGCopyAnswer_ptr, MGCopyAnswer_arm64_impl, 8) == 0) {
MSHookFunction(MGCopyAnswer_ptr + 8, (void*)new_MGCopyAnswer_internal, (void**)&orig_MGCopyAnswer_internal);
} else {
MSHookFunction(MGCopyAnswer_ptr, (void*)new_MGCopyAnswer, (void**)&orig_MGCopyAnswer);
}
}
(This only checks for arm64 on 9.3.2. Other platforms may crash in different ways, and have different assembly code, so you may need to add additional conditions into enter the hook-MGCopyAnswer_internal branch. YMMV!)
Try this code:
#import <substrate.h>
static CFTypeRef (*orig_MGCopyAnswer)(CFStringRef str);
CFTypeRef new_MGCopyAnswer(CFStringRef str)
{
return orig_MGCopyAnswer(str);
}
%ctor
{
NSString *appID = [[NSBundle mainBundle] bundleIdentifier];
if ( appID && [appID isEqualToString:#"com.test.test"]) {
void * MGCopyAnswerFn = MSFindSymbol(NULL, "_MGCopyAnswer");
MSHookFunction(MGCopyAnswerFn, (void *) new_MGCopyAnswer, (void **)& orig_MGCopyAnswer);
}
}
Currently we're implementing Libspotify in a win 7 64 bit system. Everything seems to work fine except the playback. We get data from the callback , but even using audicity on the saved audio, is filled with abnormalities. So to research further we took the win32 sample (spshell ) and modified it to save the music data to file. Same problem, definitely music with these ticks in it. I'm sure there's something simple I'm missing here, but I'm at a loss as to what could be the problem. Any help would be great since as it stands our project is at a stand still until we can resolve this.
The audio saved can be viewed here
http://uploader.crestron.com/download.php?file=8001d80992480280dba365752aeaca81
Below are the code changes I made to save the file ( for testing only )
static FILE *pFile;
int numBytesToWrite=0;
CRITICAL_SECTION m_cs;
int SP_CALLCONV music_delivery(sp_session *s, const sp_audioformat *fmt, const void *frames, int num_frames)
{
if ( num_frames == 0 )
return;
EnterCriticalSection(&m_cs);
numBytesToWrite = ( num_frames ) * fmt->channels * sizeof(short);
if (numBytesToWrite > 0 )
fwrite(frames, sizeof(short), numBytesToWrite, pFile);
LeaveCriticalSection(&m_cs);
return num_frames;
}
static void playtrack_test(void)
{
sp_error err;
InitializeCriticalSection(&m_cs);
pFile = fopen ("C:\\zzzspotify.pcm","wb");
test_start(&playtrack);
if((err = sp_session_player_load(g_session, stream_track)) != SP_ERROR_OK) {
test_report(&playtrack, "Unable to load track: %s", sp_error_message(err));
return;
}
info_report("Streaming '%s' by '%s' this will take a while", sp_track_name(stream_track),
sp_artist_name(sp_track_artist(stream_track, 0)));
sp_session_player_play(g_session, 1);
}
void SP_CALLCONV play_token_lost(sp_session *s)
{
fclose(pFile);
DeleteCriticalSection(&m_cs);
stream_track_end = 2;
notify_main_thread(g_session);
info_report("Playtoken lost");
}
static int check_streaming_done(void)
{
if(stream_track_end == 2)
test_report(&playtrack, "Playtoken lost");
else if(stream_track_end == 1)
test_ok(&playtrack);
else
return 0;
fclose(pFile);
stream_track_end = 0;
return 1;
}
It looks like this is the problem:
fwrite(frames, sizeof(short), numBytesToWrite, pFile);
The fwrite documentation states that the second argument is the "size in bytes of each element to be written", and the third is this "number of elements, each one with a size of size bytes".
The way you're calling frwritewill tell it to write numBytesToWrite * sizeof(short) bytes, which will run right off the end of the given buffer. I'm actually surprised it doesn't crash!
I'd suggest changing your fwrite call to something like:
fwrite(frames, sizeof(char), numBytesToWrite, pFile);
or:
int numSamplesToWrite = num_frames * fmt->channels;
fwrite(frames, sizeof(short), numSamplesToWrite, pFile);
Edit:
After looking at your audio in detail, I'm more convinced that this is the case. The song seems to be playing at half speed (i.e., 2x as much data is being written) and the artefacts seem to look like buffer overrun into random memory.
After start up I'd like my Linux program to drop root privileges and switch to a non-privileged account. I've found various examples online but nothing canonical for my requirements, specifically:
this is a permanent drop
both (e)uid and (e)gid should switch to non-root
only Linux support (kernel > 2.6.32)
no need for supplemental groups
The best approach I've found is:
uid_t new_uid = ...;
gid_t new_gid = ...;
gid_t rgid, egid, sgid;
if (setresgid(new_gid, new_gid, new_gid) < 0)
{
perror("setresgid");
exit(EXIT_FAILURE);
}
if (getresgid(&rgid, &egid, &sgid) < 0)
{
perror("getresgid");
exit(EXIT_FAILURE);
}
if (rgid != new_gid || egid != new_gid || sgid != new_gid)
{
printf("unexpected gid");
exit(EXIT_FAILURE);
}
if (setgroups(0, 0) != 0)
{
perror("setgroups");
exit(EXIT_FAILURE);
}
uid_t ruid, euid, suid;
if (setresuid(new_uid, new_uid, new_uid) < 0)
{
perror("setresuid");
exit(EXIT_FAILURE);
}
if (getresuid(&ruid, &euid, &suid) < 0)
{
perror("getresuid");
exit(EXIT_FAILURE);
}
if (ruid != new_uid || euid != new_uid || suid != new_uid)
{
printf("unexpected uid");
exit(EXIT_FAILURE);
}
I can wrap this in an exe and demonstrate that the uid's and gid's appear correct using:
ps -eO user,uid,ruid,suid,group,gid,rgid,sgid
The program can't bind to a privileged port or manipulate most root-owned files, so that's all good.
I've also found the captest program (included in libcap-ng-utils) which verifies that the process does not have any unexpected capabilities(7).
However, since security is a concern I'd like to be more confident that I've dropped all non-essential privileges correctly. How can I be certain?
Thanks.
The "canonical" way to do this was implemented by D.J.Bernstein in his 'setuidgid' code, which was originally used into his QMail program, nowadays included in 'daemontools'.
The actual code used in GNU coreutils is based on DJB's description of the procedure, its code is visible here https://github.com/wertarbyte/coreutils/blob/master/src/setuidgid.c