Getting a Second Kernel onboard, a repair kernel

They go by many names, P01, P59, VPW, '0411 etc. Also covering E38 and newer here.
User avatar
Gampy
Posts: 2333
Joined: Sat Dec 15, 2018 7:38 am

Getting a Second Kernel onboard, a repair kernel

Post by Gampy »

So, what is the trick to using PcmHammers kernel to receive a second kernel and execute it ??
i.e. A Repair/Recovery kernel.

Been trying without success.
Intelligence is in the details!

It is easier not to learn bad habits, then it is to break them!

If I was here to win a popularity contest, their would be no point, so I wouldn't be here!
User avatar
antus
Site Admin
Posts: 8250
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: Getting a Second Kernel onboard, a repair kernel

Post by antus »

we havnt implemented anything like that, although I'd love to see it become possible. it'd need to support mode 36 to write to arbitary locations and then jump to that address if the exectute flag is set.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
User avatar
Gampy
Posts: 2333
Joined: Sat Dec 15, 2018 7:38 am

Re: Getting a Second Kernel onboard, a repair kernel

Post by Gampy »

Code: Select all

void HandleWriteMode36()
{
.
. wacked for brevity
.
	if ((start >= 0xFF8000) && (start + length <= 0xFFCDFF))
	{
		// Copy content
		unsigned int address = 0;
		for (int index = 0; index < length; index++)
		{
			if (index % 50 == 1) ScratchWatchdog();
			address = start + index;
			*((unsigned char*)address) = MessageBuffer[10 + index];
		}

		// Notify the tool that the write succeeded.
		SendWriteSuccess(command);

		// Let the success message flush.
		LongSleepWithWatchdog();

		// Execute if requested to do so.
		if (command == 0x80)
		{
			EntryPoint entryPoint = (EntryPoint)start;
			entryPoint();
		}
	}
	else
	{
		char flashError = WriteToFlash(length, start, &MessageBuffer[10], command == 0x44);

		if (flashError == 0) SendWriteSuccess(command);
		else SendWriteFail(0, flashError);
	}
}
Is that not what the above code is ??
Intelligence is in the details!

It is easier not to learn bad habits, then it is to break them!

If I was here to win a popularity contest, their would be no point, so I wouldn't be here!
User avatar
antus
Site Admin
Posts: 8250
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: Getting a Second Kernel onboard, a repair kernel

Post by antus »

It looks like it. I was not aware it was there. Perhaps its buggy, or perhaps it does work? I guess to test it firstly you'd need to check where the message buffer is, and check where that code is then make sure there are no collisions as that copy part runs, and make sure the new code can handle the DLC, and if everything can run cleanly, it should work.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
User avatar
NSFW
Posts: 679
Joined: Fri Feb 02, 2018 3:13 pm

Re: Getting a Second Kernel onboard, a repair kernel

Post by NSFW »

I'm sure it's possible to do what you want, but it might take some debugging.

If I remember right, the kernel code you're looking at did get used in the very early days of kernel development. That was a long time ago, so I'm not 100% confident that it still works. Or that it ever worked - but I think it did work.
Please don't PM me with technical questions - start a thread instead, and send me a link to it. That way I can answer in public, and help other people who have the same question. Thanks!
User avatar
Gampy
Posts: 2333
Joined: Sat Dec 15, 2018 7:38 am

Re: Getting a Second Kernel onboard, a repair kernel

Post by Gampy »

The kernel code looks sane.

It crashes executing the second kernel.

Both kernels work stand alone at the addresses used to load them both.

I've tried, loading mini above and below kernel.

I did create my own app to upload kernels, it works stand alone both kernels.

The following is my apps kernel loading code (a hacked up version of PcmHammers *_BackgroundThread()).
Note the 'StandardKernelLoad' property used to skip code for loading the second kernel, If those parts are not skipped it crashes the PCM straight away.
I'm sure it could be cleaner .... it is what it is, a hack!

Code: Select all

            try
            {
                this.Invoke((MethodInvoker)delegate ()
                {
                    this.DisableUserInput();
                    //this.cancelButton.Enabled = true;
                });

                if (this.Vehicle == null)
                {
                    this.AddDebugMessage("ERROR: Vehicle is null.");
                    return;
                }

                this.cancellationTokenSource = new CancellationTokenSource();

                if (StandardKernelLoad)
                {
                    this.AddUserMessage("Querying operating system of current PCM.");
                    Response<uint> osidResponse = await this.Vehicle.QueryOperatingSystemId(this.cancellationTokenSource.Token);
                    if (osidResponse.Status != ResponseStatus.Success)
                    {
                        this.AddUserMessage("Operating system query failed, will retry: " + osidResponse.Status);
                        await this.Vehicle.ExitKernel();

                        if (cancellationTokenSource.Token.IsCancellationRequested)
                        {
                            return;
                        }

                        //osidResponse = await this.Vehicle.QueryOperatingSystemId(this.cancellationTokenSource.Token);
                        //if (osidResponse.Status != ResponseStatus.Success)
                        //{
                        //    this.AddUserMessage("Operating system query failed: " + osidResponse.Status);
                            //return;
                        //}
                    }

                    PcmInfo pcmInfo;
                    if (osidResponse.Status == ResponseStatus.Success)
                    {
                        // Look up the information about this PCM, based on the OSID;
                        this.AddUserMessage("OSID: " + osidResponse.Value);
                        pcmInfo = new PcmInfo(osidResponse.Value);
                    }
                    else
                    {
                        // TODO: prompt the user - 512kb or 1mb?
                        this.AddUserMessage("Unable to get operating system ID. Will assume this can be unlocked with the default seed/key algorithm.");
                        pcmInfo = new PcmInfo(0);
                    }

                    if (cancellationTokenSource.Token.IsCancellationRequested)
                    {
                        return;
                    }

                    await this.Vehicle.SuppressChatter();

                    bool unlocked = await this.Vehicle.UnlockEcu(pcmInfo.KeyAlgorithm);
                    if (!unlocked)
                    {
                        this.AddUserMessage("Unlock was not successful.");
                        return;
                    }

                    this.AddUserMessage("Unlock succeeded.");

                    if (cancellationTokenSource.Token.IsCancellationRequested)
                    {
                        return;
                    }

                    // Do the actual reading.
                    //DateTime start = DateTime.Now;
                }
                // Let us re-enable the Standard loading of the kernel.
                // it is currently only used above, and set in loadKernelButton_Click() and loadKernelButton2_Click()
                StandardKernelLoad = true;

                await this.Vehicle.SendToolPresentNotification();

                Response<byte[]> response = await this.Vehicle.LoadKernelFromFile(KernelFilename);
                if (response.Status != ResponseStatus.Success)
                {
                    AddUserMessage("Failed to load kernel from file.");
                    return;
                }

                if (cancellationTokenSource.Token.IsCancellationRequested)
                {
                    return;
                }

                this.Vehicle.ReportKernelID = false;
                if (!await this.Vehicle.PCMExecute(response.Value, KernelAddress, cancellationTokenSource.Token))
                {
                    AddUserMessage("Failed to upload kernel to PCM");
                    return;
                }

                AddUserMessage("Kernel uploaded to PCM succesfully...");
                await this.Vehicle.SetDeviceTimeout(TimeoutScenario.ReadMemoryBlock);
                await this.Vehicle.ForceSendToolPresentNotification();

            }
            catch (Exception exception)
I dunno know, guess I'll keep beating on it, maybe it will submit to my will!
Intelligence is in the details!

It is easier not to learn bad habits, then it is to break them!

If I was here to win a popularity contest, their would be no point, so I wouldn't be here!
User avatar
antus
Site Admin
Posts: 8250
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: Getting a Second Kernel onboard, a repair kernel

Post by antus »

It might be something to do with the stack. When you jump in to the new code the stack will have the call return addresses for the previous kernel already on it. You might need to reset the stack pointer somehow. Also the DLC might be in a different state from when the factory OS hands over. I dont remember ever seeing the kernel load another, though we knew we wanted it to do that one day.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
User avatar
Gampy
Posts: 2333
Joined: Sat Dec 15, 2018 7:38 am

Re: Getting a Second Kernel onboard, a repair kernel

Post by Gampy »

Something is in my head saying one of you two mentioned to me that a repair kernel or something like that was loaded by kernel and it worked.

I dunno know, maybe it's a fake memory in my oxygen deprived mind, it is getting pretty rotten.

I'll keep poking it, maybe it'll come to life ...
Intelligence is in the details!

It is easier not to learn bad habits, then it is to break them!

If I was here to win a popularity contest, their would be no point, so I wouldn't be here!
User avatar
antus
Site Admin
Posts: 8250
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: Getting a Second Kernel onboard, a repair kernel

Post by antus »

I did mention that pete mentioned that lsdroid did it for the v6, maybe thats what your thinking of. Or maybe NSFW used the code above.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
User avatar
NSFW
Posts: 679
Joined: Fri Feb 02, 2018 3:13 pm

Re: Getting a Second Kernel onboard, a repair kernel

Post by NSFW »

There are three RAM ranges to keep in mind for this:
1) where kernel A lives
2) where kernel B lives
3) the buffer that both kernels use to hold data from the DLC before copying that data to its destination.

Make sure all three of those are separate address ranges. Right now there's also a chunk set aside for the CRC lookup table but you can ignore that for now. I'm pretty sure I was playing with this kernel-upgrade idea back when we only had read working, so the kernel was much smaller back then. If you haven't already, you'd probably have to remove a bunch of code to make one small enough to fit two copies.

If you can get the factory OS code to load both kernels into their address space and run (respond to a message, or maybe just send a heartbeat message periodically) then it should also be possible to get either kernel to load the other. If not I'd look for bugs in the code that loads the 2nd kernel.
Please don't PM me with technical questions - start a thread instead, and send me a link to it. That way I can answer in public, and help other people who have the same question. Thanks!
Post Reply