Getting a Second Kernel onboard, a repair kernel

They go by many names, P01, P59, VPW, '0411 etc . Circa 1999 to 2006. All VPW OBD2 PCMs.
User avatar
Posts: 844
Joined: Sat Dec 15, 2018 7:38 am

Getting a Second Kernel onboard, a repair kernel

Postby Gampy » Sun Jan 03, 2021 1:36 am

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.
Windows 10 is like an off idle flat spot ... It stumbles when it's time to go!

Site Admin
User avatar
Posts: 6455
Joined: Sat Feb 28, 2009 8:34 pm

Re: Getting a Second Kernel onboard, a repair kernel

Postby antus » Sun Jan 03, 2021 2:58 pm

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: viewtopic.php?f=7&t=1396

User avatar
Posts: 844
Joined: Sat Dec 15, 2018 7:38 am

Re: Getting a Second Kernel onboard, a repair kernel

Postby Gampy » Sun Jan 03, 2021 3:09 pm

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 ??
Windows 10 is like an off idle flat spot ... It stumbles when it's time to go!

Site Admin
User avatar
Posts: 6455
Joined: Sat Feb 28, 2009 8:34 pm

Re: Getting a Second Kernel onboard, a repair kernel

Postby antus » Sun Jan 03, 2021 5:02 pm

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: viewtopic.php?f=7&t=1396

User avatar
Posts: 467
Joined: Fri Feb 02, 2018 3:13 pm

Re: Getting a Second Kernel onboard, a repair kernel

Postby NSFW » Mon Jan 04, 2021 4:51 pm

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
Posts: 844
Joined: Sat Dec 15, 2018 7:38 am

Re: Getting a Second Kernel onboard, a repair kernel

Postby Gampy » Mon Jan 04, 2021 10:06 pm

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!
Windows 10 is like an off idle flat spot ... It stumbles when it's time to go!

Site Admin
User avatar
Posts: 6455
Joined: Sat Feb 28, 2009 8:34 pm

Re: Getting a Second Kernel onboard, a repair kernel

Postby antus » Tue Jan 05, 2021 1:02 pm

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: viewtopic.php?f=7&t=1396

User avatar
Posts: 844
Joined: Sat Dec 15, 2018 7:38 am

Re: Getting a Second Kernel onboard, a repair kernel

Postby Gampy » Tue Jan 05, 2021 9:09 pm

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 ...
Windows 10 is like an off idle flat spot ... It stumbles when it's time to go!

Site Admin
User avatar
Posts: 6455
Joined: Sat Feb 28, 2009 8:34 pm

Re: Getting a Second Kernel onboard, a repair kernel

Postby antus » Wed Jan 06, 2021 12:51 pm

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: viewtopic.php?f=7&t=1396

User avatar
Posts: 467
Joined: Fri Feb 02, 2018 3:13 pm

Re: Getting a Second Kernel onboard, a repair kernel

Postby NSFW » Wed Jan 06, 2021 4:12 pm

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!

Next

Return to GM LS1 512Kbyte and 1Mbyte

Who is online

Users browsing this forum: No registered users and 3 guests